Files
wehub-resource-sync 41cb1c0170
OpenSSF Scorecard / scorecard (push) Failing after 0s
DCO / dco (push) Failing after 0s
CodeQL SAST / analyze (push) Failing after 1s
Deploy Pages / deploy (push) Failing after 1s
chore: import upstream snapshot with attribution
2026-07-13 12:28:05 +08:00

120 lines
5.1 KiB
C

#ifndef CBM_LSP_PERL_LSP_H
#define CBM_LSP_PERL_LSP_H
#include "type_rep.h"
#include "scope.h"
#include "type_registry.h"
#include "../cbm.h"
#include "go_lsp.h" /* CBMLSPDef reused across languages */
/* PerlLSPContext — per-file state for Perl type-aware call resolution.
* Mirrors PHPLSPContext / GoLSPContext / CLSPContext structure.
*
* Perl differs from PHP in a few ways that shape this context:
* - Packages (`package Foo::Bar;`) replace PHP namespaces. A file may
* contain several packages; current_package_qn tracks the active one.
* - Inheritance is expressed via the `@ISA` array (or `use parent`/
* `use base`), not a class keyword, so we keep an @ISA table.
* - `bless` associates a reference variable with a class at runtime;
* we track a bless var→class map for method dispatch.
* - Exporter-style imports (`use Foo qw(bar baz)`) populate an export
* import map (local name → target QN) analogous to PHP `use`. */
typedef struct {
CBMArena *arena;
const char *source;
int source_len;
const CBMTypeRegistry *registry;
CBMScope *current_scope;
/* Package state. A Perl file may declare multiple packages; this is the
* QN of the package currently in effect (dotted form). Empty string means
* the default `main` / file-level package. */
const char *current_package_qn;
/* Export import map (Exporter / `use Foo qw(...)`).
* use_local_names[i] is the symbol as referenced in this file;
* use_target_qns[i] is the fully-qualified target it resolves to. */
const char **use_local_names;
const char **use_target_qns;
int use_count;
int use_cap;
/* @ISA inheritance table: isa_pkg_qns[i] inherits from isa_parent_qns[i].
* Populated from @ISA assignments and `use parent`/`use base`. */
const char **isa_pkg_qns;
const char **isa_parent_qns;
int isa_count;
int isa_cap;
/* bless var→class map: blessed_var_names[i] holds a reference blessed
* into class blessed_class_qns[i], so $self->method() can dispatch. */
const char **blessed_var_names;
const char **blessed_class_qns;
int blessed_count;
int blessed_cap;
/* Current package/sub context. */
const char *enclosing_package_qn; /* package QN of the enclosing scope */
const char *enclosing_parent_qn; /* parent class QN (for SUPER::), or NULL */
const char *enclosing_func_qn; /* enclosing sub QN, or NULL */
const char *module_qn;
/* Output: resolved calls accumulate here. */
CBMResolvedCallArray *resolved_calls;
/* Recursion guard for perl_eval_expr_type. */
int eval_depth;
/* Recursion guard for the AST-walk passes (perl_resolve_calls_in_node /
* perl_pass1_scan). Bounds stack depth on pathologically nested input. */
int walk_depth;
/* Debug mode (CBM_LSP_DEBUG env). */
bool debug;
} PerlLSPContext;
/* Initialize a PerlLSPContext for processing one file. */
void perl_lsp_init(PerlLSPContext *ctx, CBMArena *arena, const char *source, int source_len,
const CBMTypeRegistry *registry, const char *module_qn,
CBMResolvedCallArray *out);
/* Add an export/`use` mapping (local name → target QN). */
void perl_lsp_add_use(PerlLSPContext *ctx, const char *local_name, const char *target_qn);
/* Process a file's AST: walk package decls + sub bodies, resolve calls. */
void perl_lsp_process_file(PerlLSPContext *ctx, TSNode root);
/* Evaluate a Perl expression's type. May return NULL / CBM_TYPE_UNKNOWN. */
const CBMType *perl_eval_expr_type(PerlLSPContext *ctx, TSNode node);
/* Resolve a package/class name (bare or qualified) using current package +
* the export import map. */
const char *perl_resolve_package_name(PerlLSPContext *ctx, const char *name);
/* Look up a method on a package, walking the @ISA chain (registry-based). */
const CBMRegisteredFunc *perl_lookup_method(PerlLSPContext *ctx, const char *package_qn,
const char *method_name);
/* Entry point: build registry from file defs + stdlib, then run resolution.
* Called from cbm_extract_file() via the language dispatch in cbm.c. */
void cbm_run_perl_lsp(CBMArena *arena, CBMFileResult *result, const char *source, int source_len,
TSNode root);
/* Register Perl stdlib (perlfunc builtins) + curated CPAN types into a
* registry. */
void cbm_perl_stdlib_register(CBMTypeRegistry *reg, CBMArena *arena);
/* --- Cross-file LSP resolution ---
*
* Mirrors cbm_run_php_lsp_cross / cbm_run_py_lsp_cross. Stub-declared here so
* a later plan (Phase 23, cross-file) can implement it without touching the
* wiring. Caller supplies the combined CBMLSPDef[] (file-local + cross-file)
* and a resolved import map (use → target QN). */
void cbm_run_perl_lsp_cross(CBMArena *arena, const char *source, int source_len,
const char *module_qn, CBMLSPDef *defs, int def_count,
const char **import_names, const char **import_qns, int import_count,
TSTree *cached_tree, /* NULL = parse internally */
CBMResolvedCallArray *out);
#endif /* CBM_LSP_PERL_LSP_H */