Implement Function::Parameters compatibility using native signatures and parser support

Open
#1,361 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
25/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Active
Tech stack
java, perl
Domain
compilers

Research direction

Start by reading the parser keyword-plugin API proposed in #1292 and the existing core-signature AST/runtime representation. Validate each Perl-level behavior with system Perl first, then add project-owned tests covering registration, declarations, methods, malformed syntax, eval, metadata, and both PerlOnJava backends. Done means a documented useful subset executes consistently on both backends with explicit compatibility boundaries.

Written by the indexing model from the issue text.

Description

area:cpan-port area:parser enhancement

Summary

Implement a PerlOnJava-compatible Function::Parameters provider that uses
PerlOnJava's parser/compiler infrastructure and modern Perl signatures/class
semantics where they match the module's behavior.

This is a focused consumer/port issue for the parser extension capability
proposed in #1292. It should not attempt to reproduce the Perl 5 parser ABI or
compile the module's native XS code.

Motivation and evidence

Function::Parameters is currently blocked because its latest CPAN release,
v2.002006 (2025-08-16), loads an XS implementation. The XS code installs a
Perl keyword plugin, parses declarations such as fun and method, creates
lexical parameter bindings, emits default and validation logic, and exposes
signature metadata through Function::Parameters::Info.

The CPAN reverse-dependency lookup reports 53 unique dependant distributions,
including 8 released within the last three years. Examples include
exact-fun, Data-Frame, WebService-OpenStates,
Net-Google-CivicInformation, App-Wax, HTML-Blitz, Klonk, and
Function-Return.

The CPAN compatibility run 20260910-101908-8428 showed
Mojolicious::Plugin::GraphQL failing before its own behavior was tested:
Function::Parameters could not load because no Java XS implementation was
available. Other dependency paths have the same underlying limitation.

Feasibility

A normal pure-Perl replacement is not sufficient. Function::Parameters adds
custom declaration keywords and relies on compile-time parser/optree behavior;
ordinary import, AUTOLOAD, or runtime wrappers cannot reliably make syntax
such as this work:

use Function::Parameters;
fun add($x, $y = 1) { $x + $y }
method render($self: :$format = 'html') { ... }

Source filters could rewrite a subset, but would be fragile around eval,
lexical pragma scope, nested declarations, heredocs, diagnostics, and generated
closures. They would also make JVM/interpreter behavior depend on a second
parser.

Modern Perl provides useful semantics but not a drop-in replacement:

  • Stable core signatures (enabled by use v5.36) cover positional parameters,
    defaults, slurpy arrays/hashes, and argument-count checking.
  • The experimental class feature provides class, field, method,
    ADJUST, and field :param constructor arguments.
  • Core signatures do not provide the complete Function::Parameters keyword
    model, arbitrary configured invocants, fun, named :$x parameters with
    the same rules, custom type constraints/coercions, method modifiers, or the
    Function::Parameters::Info API.

References:

Conclusion: a mostly-Perl compatibility layer is feasible, but it requires
PerlOnJava parser/compiler support. It is not feasible as a standalone pure
Perl module with no engine changes.

Proposed architecture

  1. Use #1292's lexical parser keyword-plugin API to register fun, method,
    configured aliases, and later modifiers.
  2. Parse declarations directly into the shared AST used by both execution
    backends. Do not generate backend-specific implementations.
  3. Normalize supported signatures into existing subroutine nodes, including
    lexical bindings, invocants, defaults, slurpy parameters, and call-time
    validation.
  4. Represent signature metadata in a stable compiler/runtime structure so
    Function::Parameters::info can expose it without inspecting backend
    internals.
  5. Implement the compatibility module as a small Perl provider/pragma that
    requests parser registration. Its API should degrade with a clear
    diagnostic for unsupported syntax rather than silently treating fun or
    method as ordinary barewords.

Suggested implementation phases

Phase 1: core signature subset
  • fun named and anonymous declarations;
  • ordinary required and optional positional parameters;
  • default expressions, including //= and ||= forms;
  • ignored parameters and slurpy @/% parameters;
  • exact argument-count diagnostics;
  • lexical pragma scope for use/no and nested eval.

Where semantics are identical, reuse the existing core-signature AST/runtime
representation rather than creating a parallel implementation.

Phase 2: methods and metadata
  • method declarations;
  • implicit, named, and configured invocants;
  • class-method and multi-invocant configurations where needed;
  • Function::Parameters::Info objects and parameter categorization;
  • prototypes and relevant subroutine attributes.
Phase 3: extended behavior
  • named :$parameter arguments and named-parameter slurping;
  • custom type constraints, inline checks, custom error messages, and coercion;
  • before, after, around, augment, and override method modifiers;
  • closure/lifetime behavior and debugger/source-location parity.

Compatibility boundaries

The first implementation should document any behavior that cannot be matched
exactly. In particular, do not claim complete compatibility until the following
are covered or explicitly rejected:

  • compile-time syntax errors and line/column locations;
  • indirect calls and prototype interactions;
  • recursion and anonymous functions;
  • default expressions evaluated at call time;
  • aliases and mutation behavior through @_;
  • typed parameters and custom type objects;
  • modifier composition and method cache invalidation;
  • eval STRING, nested lexical scopes, and require-time registration;
  • info() introspection and generated parameter metadata;
  • JVM/interpreter parity.

Testing and acceptance criteria

Add project-owned tests without modifying upstream tests. Validate each
Perl-level behavior with system Perl first, then require both PerlOnJava
backends to pass.

Acceptance should include:

  • parser-plugin registration and lexical removal;
  • named and anonymous fun declarations;
  • methods with invocants and defaults;
  • positional, named, ignored, and slurpy parameters;
  • malformed declarations and stable source locations;
  • nested blocks, strings, comments, heredocs, and eval;
  • default-expression side effects and recursive calls;
  • Function::Parameters::Info compatibility for the supported subset;
  • identical JVM/interpreter results;
  • a minimal Mojolicious::Plugin::GraphQL or GraphQL dependency reproducer;
  • progress toward the blocked CPAN dependants, with unsupported XS-only cases
    kept separately classified.

The issue is complete only when the provider can execute a documented useful
subset on both backends, the parser API is documented, and remaining upstream
failures have an explicit compatibility classification.

Related: #1292 (parser keyword-plugin API).

Dominant language
Perl
Stars
64
Forks
6
Avg merge
5h 18m
Merged PRs (30d)
162

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from fglock/PerlOnJava

All issues in fglock/PerlOnJava

Similar issues

More Perl issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.