175 lines
7.2 KiB
C
175 lines
7.2 KiB
C
#ifndef CBM_LSP_C_LSP_H
|
|
#define CBM_LSP_C_LSP_H
|
|
|
|
#include "type_rep.h"
|
|
#include "scope.h"
|
|
#include "type_registry.h"
|
|
#include "../cbm.h"
|
|
#include "go_lsp.h" // for CBMLSPDef, CBMResolvedCallArray
|
|
|
|
// CLSPContext holds state for C/C++ expression type evaluation within a file.
|
|
typedef struct {
|
|
CBMArena *arena;
|
|
const char *source;
|
|
int source_len;
|
|
const CBMTypeRegistry *registry;
|
|
CBMScope *current_scope;
|
|
|
|
// Include map: header_path -> namespace QN prefix
|
|
const char **include_paths;
|
|
const char **include_ns_qns;
|
|
int include_count;
|
|
|
|
// Namespace state
|
|
const char *current_namespace; // current namespace QN (e.g., "proj.ns1.ns2")
|
|
|
|
// Using namespace directives
|
|
const char **using_namespaces;
|
|
int using_ns_count;
|
|
int using_ns_cap;
|
|
|
|
// Using declarations: specific names imported into scope
|
|
const char **using_decl_names;
|
|
const char **using_decl_qns;
|
|
int using_decl_count;
|
|
int using_decl_cap;
|
|
|
|
// Namespace aliases: short -> full QN
|
|
const char **ns_alias_names;
|
|
const char **ns_alias_qns;
|
|
int ns_alias_count;
|
|
int ns_alias_cap;
|
|
|
|
// Current context
|
|
const char *enclosing_func_qn;
|
|
const char *enclosing_class_qn; // for implicit `this` resolution
|
|
const char *module_qn;
|
|
size_t module_qn_len; // cached strlen(module_qn); for stack-buffer QN building
|
|
|
|
// Negative-lookup memo for c_lookup_member_depth (depth==0 misses only).
|
|
// Open-addressing uint64 hash SET; 0 is the empty-slot sentinel. Populated
|
|
// ONLY when the Tier-2 registry is shared+read-only (registry_shared), where
|
|
// the module-prefix/base-class/short-name cascades are pure, stable functions
|
|
// of (type_qn, registry) — so a recorded miss can never turn into a hit. Lets
|
|
// the hot resolve path skip the sprintf("%s.%s") strlen storm + the O(type_count)
|
|
// short-name scan on repeated misses of the same (type_qn, member). malloc-owned;
|
|
// freed at end of c_lsp_process_file.
|
|
uint64_t *neg_memo;
|
|
int neg_memo_cap; // power-of-two; 0 until first insert
|
|
int neg_memo_count; // live entries (grow by rehash at 70% load)
|
|
|
|
// Output
|
|
CBMResolvedCallArray *resolved_calls;
|
|
|
|
// Function pointer targets: var_name -> target function QN
|
|
const char **fp_var_names;
|
|
const char **fp_target_qns;
|
|
int fp_count;
|
|
int fp_cap;
|
|
|
|
// Template parameter defaults for current template scope
|
|
const char **template_param_names; // e.g., ["T", "U"]
|
|
const CBMType **template_param_defaults; // e.g., [int_type, NULL]
|
|
int template_param_count;
|
|
|
|
// Pending template calls: member calls on TYPE_PARAM inside template functions.
|
|
// At call sites with known arg types, these are resolved retroactively.
|
|
struct {
|
|
const char *func_qn; // enclosing template function
|
|
const char *type_param; // e.g., "T"
|
|
const char *method_name; // e.g., "draw"
|
|
int arg_count;
|
|
} *pending_template_calls;
|
|
int pending_tc_count;
|
|
int pending_tc_cap;
|
|
|
|
// Flags
|
|
bool cpp_mode; // C++ features enabled
|
|
bool in_template; // currently inside template declaration
|
|
bool registry_shared; // ctx->registry is the Tier-2 cross registry, shared
|
|
// READ-ONLY across resolve workers — never mutate it
|
|
// (and never store per-worker arena pointers into it)
|
|
bool debug;
|
|
int eval_depth; // recursion depth for c_eval_expr_type (crash guard)
|
|
int eval_steps; // total expression eval calls for current file (hang guard)
|
|
int walk_depth; // c_resolve_calls_in_node self-recursion (AST nesting)
|
|
} CLSPContext;
|
|
|
|
// --- API ---
|
|
|
|
void c_lsp_init(CLSPContext *ctx, CBMArena *arena, const char *source, int source_len,
|
|
const CBMTypeRegistry *registry, const char *module_qn, bool cpp_mode,
|
|
CBMResolvedCallArray *out);
|
|
|
|
void c_lsp_add_include(CLSPContext *ctx, const char *header_path, const char *ns_qn);
|
|
|
|
void c_lsp_process_file(CLSPContext *ctx, TSNode root);
|
|
|
|
const CBMType *c_eval_expr_type(CLSPContext *ctx, TSNode node);
|
|
const CBMType *c_parse_type_node(CLSPContext *ctx, TSNode node);
|
|
void c_process_statement(CLSPContext *ctx, TSNode node);
|
|
|
|
// Look up a member (method/field) on a type, traversing base classes.
|
|
const CBMRegisteredFunc *c_lookup_member(CLSPContext *ctx, const char *type_qn,
|
|
const char *member_name);
|
|
|
|
// Type simplification: unwrap refs, aliases, pointers (like clangd simplifyType).
|
|
const CBMType *c_simplify_type(CLSPContext *ctx, const CBMType *t, bool unwrap_pointer);
|
|
|
|
// --- Entry points ---
|
|
|
|
// Single-file LSP: build registry from file defs + stdlib, run resolution.
|
|
void cbm_run_c_lsp(CBMArena *arena, CBMFileResult *result, const char *source, int source_len,
|
|
TSNode root, bool cpp_mode);
|
|
|
|
// Cross-file LSP: build registry from defs + stdlib, re-parse and resolve.
|
|
void cbm_run_c_lsp_cross(CBMArena *arena, const char *source, int source_len, const char *module_qn,
|
|
bool cpp_mode, CBMLSPDef *defs, int def_count, const char **include_paths,
|
|
const char **include_ns_qns, int include_count,
|
|
TSTree *cached_tree, // NULL = parse internally
|
|
CBMResolvedCallArray *out);
|
|
|
|
// Tier 2: build a project-wide C/C++/CUDA registry ONCE from all defs
|
|
// (filters by lang). Shared READ-ONLY across resolve workers. Def-driven
|
|
// (no AST field collection) → identical entries to the per-file build.
|
|
CBMTypeRegistry *cbm_c_build_cross_registry(CBMArena *arena, CBMLSPDef *defs, int def_count);
|
|
|
|
// Cross-file LSP using a pre-built shared registry (Tier 2). Skips the
|
|
// per-file registry build; just parse + resolve.
|
|
void cbm_run_c_lsp_cross_with_registry(CBMArena *arena, const char *source, int source_len,
|
|
const char *module_qn, bool cpp_mode,
|
|
CBMTypeRegistry *reg, // pre-built, finalized, READ-ONLY
|
|
const char **include_paths, const char **include_ns_qns,
|
|
int include_count,
|
|
TSTree *cached_tree, // NULL = parse internally
|
|
CBMResolvedCallArray *out);
|
|
|
|
// Register C stdlib types and functions into a registry.
|
|
void cbm_c_stdlib_register(CBMTypeRegistry *reg, CBMArena *arena);
|
|
|
|
// Register C++ stdlib types and functions into a registry.
|
|
void cbm_cpp_stdlib_register(CBMTypeRegistry *reg, CBMArena *arena);
|
|
|
|
// --- Batch cross-file LSP ---
|
|
|
|
// Per-file input for batch C/C++ LSP processing.
|
|
typedef struct {
|
|
const char *source;
|
|
int source_len;
|
|
const char *module_qn;
|
|
bool cpp_mode;
|
|
TSTree *cached_tree; // from TSTree caching (NULL = parse internally)
|
|
CBMLSPDef *defs; // combined file-local + cross-file defs
|
|
int def_count;
|
|
const char **include_paths; // parallel arrays, include_count long
|
|
const char **include_ns_qns;
|
|
int include_count;
|
|
} CBMBatchCLSPFile;
|
|
|
|
// Process multiple C/C++ files' cross-file LSP in one CGo call.
|
|
// out must point to file_count pre-zeroed CBMResolvedCallArray structs.
|
|
void cbm_batch_c_lsp_cross(CBMArena *arena, CBMBatchCLSPFile *files, int file_count,
|
|
CBMResolvedCallArray *out);
|
|
|
|
#endif // CBM_LSP_C_LSP_H
|