Summary
Perl is already a first-class parsed language in CBM — CBM_LANG_PERL is fully registered in internal/cbm/lang_specs.c (subroutine/use/require/call/branch/var node-type mappings + tree_sitter_perl), so .pl/.pm files are structurally indexed today (definitions, calls, imports, branches, variables).
What Perl lacks is the second tier: a hand-written type-aware LSP resolution module (internal/cbm/lsp/perl_lsp.c). Today 10 languages have one — Go, C/C++/CUDA, PHP, Python, JS/TS/TSX, C#, Java, Kotlin, Rust — dispatched in cbm.c (cbm_run_*_lsp). Perl has no module and no dispatch branch, so Perl call/usage edges are resolved by tree-sitter + textual heuristics only, with no package/method/inheritance resolution.
This issue proposes adding perl_lsp.c to promote Perl from the structural tier to the semantic-resolution tier.
Motivation
Without LSP-tier resolution, Perl graphs miss the edges that matter most for navigation and impact analysis:
$obj->method() / Class->method() / $self->method() calls don't resolve to the defining subroutine.
- Inheritance via
@ISA / use parent / use base is invisible, so inherited-method calls are unresolved.
use Foo::Bar / require don't link to the target package's symbols across files.
Exporter-imported subs aren't mapped to their origin.
Perl remains widely used in systems tooling, bioinformatics, and legacy enterprise codebases — exactly the "large, hard-to-navigate" codebases CBM targets.
Proposed scope (full parity with the PHP module)
php_lsp.c is the closest analog — dynamic, package/namespace-based, OOP-by-convention — and is the model to mirror:
- Package resolution:
package Foo::Bar;, use/require → cross-file package symbol tables.
- OOP method resolution:
$self->m, Class->m, $obj->m on blessed references; method-resolution order via @ISA, use parent, use base.
- Subroutine resolution: within-package and cross-package calls;
Exporter (@EXPORT/@EXPORT_OK) import maps.
- Expression/type tracking: sigil-aware variable tracking (
$/@/%); blessed-ref type tracking through assignments (my $x = Foo->new); recursion-guarded expression-type evaluation, mirroring php_eval_expr_type.
- Builtins:
perlfunc core-builtin awareness; optional common-CPAN stdlib seed (mirrors the per-language lsp/generated/*_stdlib_data.c pattern).
Implementation outline
internal/cbm/lsp/perl_lsp.{c,h} — PerlLSPContext mirroring PHPLSPContext; reuse shared infra (type_rep.h, scope.h, type_registry.h, CBMLSPDef).
- Public entry
cbm_run_perl_lsp(a, result, source, source_len, root).
- Dispatch branch in
cbm.c (if (language == CBM_LANG_PERL) cbm_run_perl_lsp(...)).
- Tests:
tests/test_perl_lsp.c (+ Makefile.cbm wiring), following test_php_lsp.c.
- Validate against a real Perl project before submission (per CONTRIBUTING).
Notes
- This is the LSP/semantic tier only; grammar/parsing support already exists, so this is an enhancement to existing Perl coverage rather than net-new language onboarding.
- Reference modules:
internal/cbm/lsp/php_lsp.c (primary), py_lsp.c (dynamic-typing patterns).
Summary
Perl is already a first-class parsed language in CBM —
CBM_LANG_PERLis fully registered ininternal/cbm/lang_specs.c(subroutine/use/require/call/branch/var node-type mappings +tree_sitter_perl), so.pl/.pmfiles are structurally indexed today (definitions, calls, imports, branches, variables).What Perl lacks is the second tier: a hand-written type-aware LSP resolution module (
internal/cbm/lsp/perl_lsp.c). Today 10 languages have one — Go, C/C++/CUDA, PHP, Python, JS/TS/TSX, C#, Java, Kotlin, Rust — dispatched incbm.c(cbm_run_*_lsp). Perl has no module and no dispatch branch, so Perl call/usage edges are resolved by tree-sitter + textual heuristics only, with no package/method/inheritance resolution.This issue proposes adding
perl_lsp.cto promote Perl from the structural tier to the semantic-resolution tier.Motivation
Without LSP-tier resolution, Perl graphs miss the edges that matter most for navigation and impact analysis:
$obj->method()/Class->method()/$self->method()calls don't resolve to the defining subroutine.@ISA/use parent/use baseis invisible, so inherited-method calls are unresolved.use Foo::Bar/requiredon't link to the target package's symbols across files.Exporter-imported subs aren't mapped to their origin.Perl remains widely used in systems tooling, bioinformatics, and legacy enterprise codebases — exactly the "large, hard-to-navigate" codebases CBM targets.
Proposed scope (full parity with the PHP module)
php_lsp.cis the closest analog — dynamic, package/namespace-based, OOP-by-convention — and is the model to mirror:package Foo::Bar;,use/require→ cross-file package symbol tables.$self->m,Class->m,$obj->mon blessed references; method-resolution order via@ISA,use parent,use base.Exporter(@EXPORT/@EXPORT_OK) import maps.$/@/%); blessed-ref type tracking through assignments (my $x = Foo->new); recursion-guarded expression-type evaluation, mirroringphp_eval_expr_type.perlfunccore-builtin awareness; optional common-CPAN stdlib seed (mirrors the per-languagelsp/generated/*_stdlib_data.cpattern).Implementation outline
internal/cbm/lsp/perl_lsp.{c,h}—PerlLSPContextmirroringPHPLSPContext; reuse shared infra (type_rep.h,scope.h,type_registry.h,CBMLSPDef).cbm_run_perl_lsp(a, result, source, source_len, root).cbm.c(if (language == CBM_LANG_PERL) cbm_run_perl_lsp(...)).tests/test_perl_lsp.c(+Makefile.cbmwiring), followingtest_php_lsp.c.Notes
internal/cbm/lsp/php_lsp.c(primary),py_lsp.c(dynamic-typing patterns).