重构语法树/符号表
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
#include "./builder.hpp"
|
||||
#include "../collector/symbol_collector.hpp"
|
||||
#include "../collector/incremental_collector.hpp"
|
||||
#include "../incremental/incremental_engine.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
// ==================== 构造和析构 ====================
|
||||
|
||||
SymbolTableBuilder::SymbolTableBuilder() :
|
||||
incremental_enabled_(false)
|
||||
{
|
||||
}
|
||||
|
||||
SymbolTableBuilder::~SymbolTableBuilder() = default;
|
||||
|
||||
// ==================== 构建接口 ====================
|
||||
|
||||
bool SymbolTableBuilder::Build(const std::vector<ast::ASTNode>& nodes)
|
||||
{
|
||||
// 清空错误
|
||||
error_reporter_.Clear();
|
||||
|
||||
// 初始化统计信息
|
||||
stats_ = BuildStatistics{};
|
||||
stats_.is_incremental = false;
|
||||
stats_.total_symbols = nodes.size();
|
||||
|
||||
// 创建收集上下文
|
||||
CollectorContext context(registry_, error_reporter_);
|
||||
|
||||
// 创建基础收集器并执行
|
||||
SymbolCollector collector(context);
|
||||
bool success = collector.Collect(nodes);
|
||||
|
||||
// 更新统计信息
|
||||
stats_.success = success && !error_reporter_.HasErrors();
|
||||
stats_.new_symbols = stats_.total_symbols;
|
||||
stats_.reused_symbols = 0;
|
||||
stats_.reuse_rate = 0.0;
|
||||
|
||||
// 完整构建后,如果启用增量,则构建缓存
|
||||
if (stats_.success && incremental_enabled_ && incremental_engine_)
|
||||
{
|
||||
incremental_engine_->BuildCache(registry_);
|
||||
}
|
||||
|
||||
return stats_.success;
|
||||
}
|
||||
|
||||
bool SymbolTableBuilder::BuildIncremental(
|
||||
const ast::IncrementalParseResult& parse_result)
|
||||
{
|
||||
// 检查增量是否启用
|
||||
if (!incremental_enabled_ || !incremental_engine_)
|
||||
{
|
||||
// 增量未启用,退回完整构建
|
||||
return Build(parse_result.result.nodes);
|
||||
}
|
||||
|
||||
// 清空错误
|
||||
error_reporter_.Clear();
|
||||
|
||||
// 初始化统计信息
|
||||
stats_ = BuildStatistics{};
|
||||
stats_.is_incremental = true;
|
||||
stats_.total_symbols = parse_result.result.nodes.size();
|
||||
|
||||
// 创建收集上下文
|
||||
CollectorContext context(registry_, error_reporter_);
|
||||
|
||||
// 创建增量收集器并执行
|
||||
IncrementalCollector collector(context, *incremental_engine_);
|
||||
bool success = collector.CollectIncremental(parse_result);
|
||||
|
||||
// 更新统计信息
|
||||
stats_.reused_symbols = collector.GetReusedCount();
|
||||
stats_.new_symbols = collector.GetNewCount();
|
||||
|
||||
// 修复:防止除零
|
||||
if (stats_.total_symbols > 0)
|
||||
{
|
||||
stats_.reuse_rate = static_cast<double>(stats_.reused_symbols) / stats_.total_symbols;
|
||||
}
|
||||
else
|
||||
{
|
||||
stats_.reuse_rate = 0.0;
|
||||
}
|
||||
|
||||
stats_.success = success && !error_reporter_.HasErrors();
|
||||
|
||||
// 检查缓存大小,必要时进行清理
|
||||
if (incremental_engine_->GetCacheSize() > 10000) // 可配置
|
||||
{
|
||||
// LRU 会自动处理,这里只是检查
|
||||
// 如果需要强制限制,可以调用 SetMaxCacheSize
|
||||
}
|
||||
|
||||
return stats_.success;
|
||||
}
|
||||
|
||||
// ==================== 访问器 ====================
|
||||
|
||||
const std::vector<Error>& SymbolTableBuilder::GetErrors() const
|
||||
{
|
||||
return error_reporter_.GetErrors();
|
||||
}
|
||||
|
||||
bool SymbolTableBuilder::HasErrors() const
|
||||
{
|
||||
return error_reporter_.HasErrors();
|
||||
}
|
||||
|
||||
size_t SymbolTableBuilder::ErrorCount() const
|
||||
{
|
||||
return error_reporter_.ErrorCount();
|
||||
}
|
||||
|
||||
void SymbolTableBuilder::ClearErrors()
|
||||
{
|
||||
error_reporter_.Clear();
|
||||
}
|
||||
|
||||
// ==================== 增量配置 ====================
|
||||
|
||||
void SymbolTableBuilder::EnableIncremental(bool enable)
|
||||
{
|
||||
incremental_enabled_ = enable;
|
||||
|
||||
if (enable && !incremental_engine_)
|
||||
{
|
||||
incremental_engine_ = std::make_unique<IncrementalEngine>();
|
||||
}
|
||||
}
|
||||
|
||||
void SymbolTableBuilder::SetMaxCacheSize(size_t max_size)
|
||||
{
|
||||
if (incremental_engine_)
|
||||
{
|
||||
incremental_engine_->SetMaxCacheSize(max_size);
|
||||
}
|
||||
}
|
||||
|
||||
void SymbolTableBuilder::ClearCache()
|
||||
{
|
||||
if (incremental_engine_)
|
||||
{
|
||||
incremental_engine_->Clear();
|
||||
}
|
||||
}
|
||||
|
||||
size_t SymbolTableBuilder::GetCacheSize() const
|
||||
{
|
||||
if (incremental_engine_)
|
||||
{
|
||||
return incremental_engine_->GetCacheSize();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include "../../ast/types.hpp"
|
||||
#include "../../ast/deserializer.hpp"
|
||||
#include "../core/registry.hpp"
|
||||
#include "../core/error.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
// 前向声明
|
||||
class IncrementalEngine;
|
||||
|
||||
// ==================== 构建统计信息 ====================
|
||||
|
||||
struct BuildStatistics
|
||||
{
|
||||
size_t total_symbols = 0; // 总符号数
|
||||
size_t reused_symbols = 0; // 复用的符号数
|
||||
size_t new_symbols = 0; // 新创建的符号数
|
||||
double reuse_rate = 0.0; // 复用率
|
||||
bool is_incremental = false; // 是否为增量构建
|
||||
bool success = false; // 构建是否成功
|
||||
};
|
||||
|
||||
// ==================== 符号表构建器 ====================
|
||||
|
||||
/**
|
||||
* 符号表构建器 - 简化为调度器
|
||||
*
|
||||
* 职责:
|
||||
* - 提供构建入口(完整/增量)
|
||||
* - 管理核心组件(Registry、ErrorReporter)
|
||||
* - 管理增量引擎(可选)
|
||||
* - 收集和提供统计信息
|
||||
*
|
||||
* 不负责:
|
||||
* - 具体的符号收集逻辑(委托给 Collector)
|
||||
* - 增量细节(委托给 IncrementalEngine)
|
||||
* - 语义分析(属于后续阶段)
|
||||
*/
|
||||
class SymbolTableBuilder
|
||||
{
|
||||
public:
|
||||
SymbolTableBuilder();
|
||||
~SymbolTableBuilder();
|
||||
|
||||
// 禁止拷贝
|
||||
SymbolTableBuilder(const SymbolTableBuilder&) = delete;
|
||||
SymbolTableBuilder& operator=(const SymbolTableBuilder&) = delete;
|
||||
|
||||
bool Build(const std::vector<ast::ASTNode>& nodes);
|
||||
bool BuildIncremental(const ast::IncrementalParseResult& parse_result);
|
||||
|
||||
SymbolRegistry& GetRegistry() { return registry_; }
|
||||
const SymbolRegistry& GetRegistry() const { return registry_; }
|
||||
|
||||
const std::vector<Error>& GetErrors() const;
|
||||
bool HasErrors() const;
|
||||
size_t ErrorCount() const;
|
||||
void ClearErrors();
|
||||
|
||||
BuildStatistics GetStatistics() const { return stats_; }
|
||||
|
||||
void EnableIncremental(bool enable);
|
||||
void SetMaxCacheSize(size_t max_size);
|
||||
void ClearCache();
|
||||
size_t GetCacheSize() const;
|
||||
bool IsIncrementalEnabled() const { return incremental_enabled_; }
|
||||
|
||||
private:
|
||||
// 核心组件
|
||||
SymbolRegistry registry_;
|
||||
ErrorReporter error_reporter_;
|
||||
|
||||
// 增量支持(可选)
|
||||
std::unique_ptr<IncrementalEngine> incremental_engine_;
|
||||
bool incremental_enabled_;
|
||||
|
||||
// 统计信息
|
||||
BuildStatistics stats_;
|
||||
};
|
||||
|
||||
// ==================== 便捷函数 ====================
|
||||
|
||||
/**
|
||||
* 便捷函数:一次性构建符号表
|
||||
*
|
||||
* @param nodes AST节点列表
|
||||
* @param errors 可选的错误输出参数
|
||||
* @return 构建好的符号注册表(移动语义)
|
||||
*/
|
||||
inline SymbolRegistry BuildSymbolTable(const std::vector<ast::ASTNode>& nodes, std::vector<Error>* errors = nullptr)
|
||||
{
|
||||
SymbolTableBuilder builder;
|
||||
builder.Build(nodes);
|
||||
|
||||
if (errors)
|
||||
*errors = builder.GetErrors();
|
||||
|
||||
// 移动 Registry(避免拷贝)
|
||||
return std::move(builder.GetRegistry());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
#pragma once
|
||||
|
||||
#include <sstream>
|
||||
#include "../core/registry.hpp"
|
||||
#include "../core/error.hpp"
|
||||
#include "../factory/scope_manager.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
/**
|
||||
* 收集上下文 - 封装收集过程中的共享状态
|
||||
*
|
||||
* 职责:
|
||||
* - 提供对 Registry、ErrorReporter、ScopeManager 的统一访问
|
||||
* - 维护当前上下文(当前 Unit、当前 Class)
|
||||
* - 提供便捷的错误报告接口
|
||||
*/
|
||||
struct CollectorContext
|
||||
{
|
||||
SymbolRegistry& registry;
|
||||
ErrorReporter& error_reporter;
|
||||
ScopeManager scope_manager;
|
||||
|
||||
// 当前上下文
|
||||
Unit* current_unit = nullptr;
|
||||
Class* current_class = nullptr;
|
||||
|
||||
CollectorContext(SymbolRegistry& reg, ErrorReporter& reporter) :
|
||||
registry(reg), error_reporter(reporter), scope_manager(reg.GlobalScope())
|
||||
{
|
||||
}
|
||||
|
||||
// 便捷访问
|
||||
Table* CurrentScope() { return scope_manager.Current(); }
|
||||
Table* GlobalScope() { return registry.GlobalScope(); }
|
||||
|
||||
// ==================== 改进的错误报告 ====================
|
||||
|
||||
void ReportError(ErrorKind kind, const std::string& msg, const ast::Location& loc)
|
||||
{
|
||||
error_reporter.Report(kind, msg, loc);
|
||||
}
|
||||
|
||||
void ReportDuplicateDefinition(const std::string& name, const ast::Location& loc)
|
||||
{
|
||||
// 查找已存在的符号位置
|
||||
auto existing = CurrentScope()->LookupLocal(name);
|
||||
if (existing && existing.symbol)
|
||||
{
|
||||
std::ostringstream msg;
|
||||
msg << "Symbol '" << name << "' already defined at "
|
||||
<< existing.symbol->location.start_line << ":"
|
||||
<< existing.symbol->location.start_column;
|
||||
error_reporter.Report(ErrorKind::kDuplicateDefinition, msg.str(), loc);
|
||||
}
|
||||
else
|
||||
{
|
||||
error_reporter.ReportDuplicateDefinition(name, loc);
|
||||
}
|
||||
}
|
||||
|
||||
void ReportSignatureConflict(const std::string& name, const ast::Location& loc)
|
||||
{
|
||||
// 查找冲突的函数重载
|
||||
auto overloads = CurrentScope()->LookupOverloads(name);
|
||||
if (!overloads.empty())
|
||||
{
|
||||
std::ostringstream msg;
|
||||
msg << "Function signature conflict: '" << name
|
||||
<< "' (conflicts with overload at "
|
||||
<< overloads[0]->location.start_line << ":"
|
||||
<< overloads[0]->location.start_column << ")";
|
||||
error_reporter.Report(ErrorKind::kSignatureConflict, msg.str(), loc);
|
||||
}
|
||||
else
|
||||
{
|
||||
error_reporter.Report(ErrorKind::kSignatureConflict,
|
||||
"Function signature conflict: " + name,
|
||||
loc);
|
||||
}
|
||||
}
|
||||
|
||||
void ReportUnitConflict(const std::string& name, const ast::Location& loc)
|
||||
{
|
||||
auto existing_unit = registry.FindUnit(name);
|
||||
if (existing_unit)
|
||||
{
|
||||
std::ostringstream msg;
|
||||
msg << "Unit '" << name << "' already defined at "
|
||||
<< existing_unit->location.start_line << ":"
|
||||
<< existing_unit->location.start_column;
|
||||
error_reporter.Report(ErrorKind::kDuplicateDefinition, msg.str(), loc);
|
||||
}
|
||||
else
|
||||
{
|
||||
error_reporter.ReportDuplicateDefinition(name, loc);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
#include "./incremental_collector.hpp"
|
||||
#include "../incremental/incremental_engine.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
IncrementalCollector::IncrementalCollector(CollectorContext& context, IncrementalEngine& engine) :
|
||||
SymbolCollector(context), engine_(engine)
|
||||
{
|
||||
}
|
||||
|
||||
bool IncrementalCollector::CollectIncremental(const ast::IncrementalParseResult& parse_result)
|
||||
{
|
||||
// 重置统计
|
||||
reused_count_ = 0;
|
||||
new_count_ = 0;
|
||||
|
||||
// 构建变化节点索引
|
||||
std::unordered_set<size_t> changed_set(
|
||||
parse_result.changed_indices.begin(),
|
||||
parse_result.changed_indices.end());
|
||||
|
||||
// 处理所有节点
|
||||
for (size_t i = 0; i < parse_result.result.nodes.size(); ++i)
|
||||
{
|
||||
const auto& node = parse_result.result.nodes[i];
|
||||
bool is_changed = changed_set.count(i) > 0;
|
||||
|
||||
if (!ProcessNode(node, is_changed))
|
||||
return false;
|
||||
}
|
||||
|
||||
return !ctx_.error_reporter.HasErrors();
|
||||
}
|
||||
|
||||
bool IncrementalCollector::ProcessNode(const ast::ASTNode& node, bool is_changed)
|
||||
{
|
||||
if (is_changed)
|
||||
{
|
||||
// 节点已变化,必须重新收集
|
||||
new_count_++;
|
||||
|
||||
bool success = Visit(node);
|
||||
|
||||
if (success)
|
||||
{
|
||||
// 收集成功后,缓存新符号
|
||||
CacheCurrentSymbol(node);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 节点未变化,尝试复用缓存
|
||||
if (TryReuseFromCache(node))
|
||||
{
|
||||
reused_count_++;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 缓存未命中,重新收集
|
||||
new_count_++;
|
||||
bool success = Visit(node);
|
||||
|
||||
if (success)
|
||||
{
|
||||
CacheCurrentSymbol(node);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IncrementalCollector::TryReuseFromCache(const ast::ASTNode& node)
|
||||
{
|
||||
// 委托给增量引擎,传入 Registry 用于 Unit 复用
|
||||
return engine_.TryReuseSymbol(node, ctx_.CurrentScope(), &ctx_.registry);
|
||||
}
|
||||
|
||||
void IncrementalCollector::CacheCurrentSymbol(const ast::ASTNode& node)
|
||||
{
|
||||
// 委托给增量引擎
|
||||
engine_.CacheSymbol(node, ctx_.CurrentScope());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include "./symbol_collector.hpp"
|
||||
#include "../../ast/deserializer.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
// 前向声明
|
||||
class IncrementalEngine;
|
||||
|
||||
/**
|
||||
* 增量符号收集器
|
||||
*
|
||||
* 职责:
|
||||
* - 继承基础收集器的所有能力
|
||||
* - 根据节点是否变化决定复用或重新收集
|
||||
* - 委托 IncrementalEngine 进行缓存操作
|
||||
* - 收集统计信息
|
||||
*/
|
||||
class IncrementalCollector : public SymbolCollector
|
||||
{
|
||||
public:
|
||||
IncrementalCollector(CollectorContext& context, IncrementalEngine& engine);
|
||||
|
||||
// 增量收集入口
|
||||
bool CollectIncremental(const ast::IncrementalParseResult& parse_result);
|
||||
|
||||
// 统计信息
|
||||
size_t GetReusedCount() const { return reused_count_; }
|
||||
size_t GetNewCount() const { return new_count_; }
|
||||
|
||||
private:
|
||||
// 处理单个节点(判断是复用还是重新收集)
|
||||
bool ProcessNode(const ast::ASTNode& node, bool is_changed);
|
||||
|
||||
// 尝试从缓存复用符号
|
||||
bool TryReuseFromCache(const ast::ASTNode& node);
|
||||
|
||||
// 缓存当前收集的符号
|
||||
void CacheCurrentSymbol(const ast::ASTNode& node);
|
||||
|
||||
private:
|
||||
IncrementalEngine& engine_;
|
||||
size_t reused_count_ = 0;
|
||||
size_t new_count_ = 0;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,518 @@
|
||||
#include "./symbol_collector.hpp"
|
||||
#include "../utils/type.hpp"
|
||||
#include "../factory/factory.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
SymbolCollector::SymbolCollector(CollectorContext& context) :
|
||||
ctx_(context)
|
||||
{
|
||||
}
|
||||
|
||||
bool SymbolCollector::Collect(const std::vector<ast::ASTNode>& nodes)
|
||||
{
|
||||
for (const auto& node : nodes)
|
||||
{
|
||||
if (!Visit(node))
|
||||
return false;
|
||||
}
|
||||
return !ctx_.error_reporter.HasErrors();
|
||||
}
|
||||
|
||||
// ==================== AST 访问 ====================
|
||||
|
||||
bool SymbolCollector::Visit(const ast::ASTNode& node)
|
||||
{
|
||||
if (std::holds_alternative<std::monostate>(node))
|
||||
return true;
|
||||
|
||||
if (auto* unit = std::get_if<ast::UnitDefinition>(&node))
|
||||
return CollectUnit(*unit);
|
||||
|
||||
if (auto* global = std::get_if<ast::GlobalDeclaration>(&node))
|
||||
return CollectGlobal(*global);
|
||||
|
||||
if (auto* static_decl = std::get_if<ast::StaticDeclaration>(&node))
|
||||
return CollectStatic(*static_decl);
|
||||
|
||||
if (auto* var = std::get_if<ast::VarDeclaration>(&node))
|
||||
return CollectVariable(*var);
|
||||
|
||||
if (auto* constant = std::get_if<ast::ConstDeclaration>(&node))
|
||||
return CollectConstant(*constant);
|
||||
|
||||
if (auto* stmt = std::get_if<ast::AssignmentStatement>(&node))
|
||||
return CollectAssignment(*stmt);
|
||||
|
||||
if (auto* func_def = std::get_if<ast::FunctionDefinition>(&node))
|
||||
return CollectFunctionDef(*func_def);
|
||||
|
||||
if (auto* cls = std::get_if<ast::ClassDefinition>(&node))
|
||||
return CollectClass(*cls);
|
||||
|
||||
if (auto* uses = std::get_if<ast::UsesClause>(&node))
|
||||
return CollectUsesClause(*uses);
|
||||
|
||||
// 跳过表达式和块
|
||||
if (std::holds_alternative<ast::Expression>(node) ||
|
||||
std::holds_alternative<ast::Block>(node))
|
||||
return true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ==================== 收集方法 ====================
|
||||
|
||||
bool SymbolCollector::CollectUnit(const ast::UnitDefinition& unit)
|
||||
{
|
||||
auto unit_symbol = factory::CreateUnit(unit.name, unit.location);
|
||||
|
||||
if (!TryInsertUnit(unit_symbol))
|
||||
return false;
|
||||
|
||||
ctx_.current_unit = unit_symbol.get();
|
||||
|
||||
// 创建 interface 和 implementation 作用域
|
||||
unit_symbol->interface_symbols =
|
||||
std::make_unique<Table>(ScopeKind::kInterface, ctx_.GlobalScope());
|
||||
unit_symbol->implementation_symbols =
|
||||
std::make_unique<Table>(ScopeKind::kImplementation, ctx_.GlobalScope());
|
||||
|
||||
// 收集 uses 子句
|
||||
if (unit.uses)
|
||||
CollectUsesClause(*unit.uses);
|
||||
|
||||
// 收集各部分的声明
|
||||
CollectInScope(unit_symbol->interface_symbols.get(), unit.interface_statements);
|
||||
CollectInScope(unit_symbol->implementation_symbols.get(), unit.implementation_statements);
|
||||
CollectInScope(unit_symbol->implementation_symbols.get(), unit.initialization_statements);
|
||||
CollectInScope(unit_symbol->implementation_symbols.get(), unit.finalization_statements);
|
||||
|
||||
ctx_.current_unit = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SymbolCollector::CollectGlobal(const ast::GlobalDeclaration& global)
|
||||
{
|
||||
TypeInfo type = global.type_name ?
|
||||
TypeFactory::FromAnnotation(*global.type_name) :
|
||||
TypeInfo();
|
||||
|
||||
auto var_symbol = factory::CreateVariable(
|
||||
global.name, Kind::kGlobalVariable, global.location, type);
|
||||
|
||||
if (global.value)
|
||||
var_symbol->initialization_expr = global.value->text;
|
||||
|
||||
return TryInsert(var_symbol);
|
||||
}
|
||||
|
||||
bool SymbolCollector::CollectStatic(const ast::StaticDeclaration& decl)
|
||||
{
|
||||
TypeInfo type = decl.type_name ?
|
||||
TypeFactory::FromAnnotation(*decl.type_name) :
|
||||
TypeInfo();
|
||||
|
||||
auto var_symbol = factory::CreateVariable(
|
||||
decl.name, Kind::kStaticVariable, decl.location, type);
|
||||
|
||||
var_symbol->attributes.is_static = true;
|
||||
|
||||
if (decl.value)
|
||||
var_symbol->initialization_expr = decl.value->text;
|
||||
|
||||
return TryInsert(var_symbol);
|
||||
}
|
||||
|
||||
bool SymbolCollector::CollectVariable(const ast::VarDeclaration& var)
|
||||
{
|
||||
TypeInfo type = var.type_name ?
|
||||
TypeFactory::FromAnnotation(*var.type_name) :
|
||||
TypeInfo();
|
||||
|
||||
auto var_symbol = factory::CreateVariable(
|
||||
var.name, Kind::kVariable, var.location, type);
|
||||
|
||||
if (var.value)
|
||||
var_symbol->initialization_expr = var.value->text;
|
||||
|
||||
return TryInsert(var_symbol);
|
||||
}
|
||||
|
||||
bool SymbolCollector::CollectConstant(const ast::ConstDeclaration& constant)
|
||||
{
|
||||
TypeInfo type = constant.type_name ?
|
||||
TypeFactory::FromAnnotation(*constant.type_name) :
|
||||
TypeInfo();
|
||||
|
||||
auto const_symbol = factory::CreateConstant(
|
||||
constant.name, constant.location, type, constant.value.text);
|
||||
|
||||
return TryInsert(const_symbol);
|
||||
}
|
||||
|
||||
bool SymbolCollector::CollectAssignment(const ast::AssignmentStatement& stmt)
|
||||
{
|
||||
TypeInfo type;
|
||||
|
||||
auto var_symbol = factory::CreateVariable(
|
||||
stmt.name, Kind::kVariable, stmt.location, type);
|
||||
|
||||
var_symbol->initialization_expr = stmt.value.text;
|
||||
|
||||
return TryInsert(var_symbol);
|
||||
}
|
||||
|
||||
bool SymbolCollector::CollectFunctionDef(const ast::FunctionDefinition& func)
|
||||
{
|
||||
Signature sig = CreateSignature(func.signature);
|
||||
|
||||
auto func_symbol = factory::CreateFunction(
|
||||
func.name, func.location, sig);
|
||||
|
||||
if (!TryInsertFunction(func_symbol, func.location))
|
||||
return false;
|
||||
|
||||
// 收集函数体
|
||||
if (!func.body.statements.empty())
|
||||
CollectFunctionBody(func_symbol.get(), func.body);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SymbolCollector::CollectClass(const ast::ClassDefinition& class_def)
|
||||
{
|
||||
auto class_symbol = factory::CreateClass(
|
||||
class_def.name, class_def.location);
|
||||
|
||||
// 存储父类名称(字符串形式,不解析引用)
|
||||
class_symbol->parent_names = class_def.parents;
|
||||
|
||||
if (!TryInsert(class_symbol))
|
||||
return false;
|
||||
|
||||
// 创建成员作用域
|
||||
class_symbol->members = std::make_unique<Table>(
|
||||
ScopeKind::kClass, ctx_.CurrentScope());
|
||||
|
||||
ctx_.current_class = class_symbol.get();
|
||||
|
||||
// 进入类作用域,收集成员
|
||||
auto guard = ctx_.scope_manager.EnterScope(class_symbol->members.get());
|
||||
for (const auto& member : class_def.members)
|
||||
{
|
||||
CollectClassMember(member, class_symbol.get());
|
||||
}
|
||||
|
||||
ctx_.current_class = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SymbolCollector::CollectUsesClause(const ast::UsesClause& uses)
|
||||
{
|
||||
if (ctx_.current_unit)
|
||||
ctx_.current_unit->uses = uses.units;
|
||||
return true;
|
||||
}
|
||||
|
||||
// ==================== 类成员收集 ====================
|
||||
|
||||
bool SymbolCollector::CollectClassMember(const ast::ClassMember& member, Class* owner)
|
||||
{
|
||||
if (std::holds_alternative<std::monostate>(member.content))
|
||||
return true;
|
||||
|
||||
Access access = member.access;
|
||||
|
||||
if (auto* var = std::get_if<ast::VarDeclaration>(&member.content))
|
||||
return CollectMemberVariable(*var, access);
|
||||
|
||||
if (auto* static_decl = std::get_if<ast::StaticDeclaration>(&member.content))
|
||||
return CollectMemberStatic(*static_decl, access);
|
||||
|
||||
if (auto* method = std::get_if<ast::Method>(&member.content))
|
||||
return CollectMemberMethod(*method, access, owner);
|
||||
|
||||
if (auto* property = std::get_if<ast::Property>(&member.content))
|
||||
return CollectMemberProperty(*property, access);
|
||||
|
||||
if (auto* ctor = std::get_if<ast::ConstructorDeclaration>(&member.content))
|
||||
return CollectMemberConstructor(*ctor, access, owner);
|
||||
|
||||
if (auto* dtor = std::get_if<ast::DestructorDeclaration>(&member.content))
|
||||
return CollectMemberDestructor(*dtor, access, owner);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SymbolCollector::CollectMemberVariable(const ast::VarDeclaration& var, Access access)
|
||||
{
|
||||
TypeInfo type = var.type_name ?
|
||||
TypeFactory::FromAnnotation(*var.type_name) :
|
||||
TypeInfo();
|
||||
|
||||
auto var_symbol = factory::CreateVariable(
|
||||
var.name, Kind::kVariable, var.location, type);
|
||||
|
||||
var_symbol->attributes.access = access;
|
||||
|
||||
if (var.value)
|
||||
var_symbol->initialization_expr = var.value->text;
|
||||
|
||||
return TryInsert(var_symbol);
|
||||
}
|
||||
|
||||
bool SymbolCollector::CollectMemberStatic(const ast::StaticDeclaration& decl, Access access)
|
||||
{
|
||||
TypeInfo type = decl.type_name ?
|
||||
TypeFactory::FromAnnotation(*decl.type_name) :
|
||||
TypeInfo();
|
||||
|
||||
auto var_symbol = factory::CreateVariable(
|
||||
decl.name, Kind::kStaticVariable, decl.location, type);
|
||||
|
||||
var_symbol->attributes.access = access;
|
||||
var_symbol->attributes.is_static = true;
|
||||
|
||||
if (decl.value)
|
||||
var_symbol->initialization_expr = decl.value->text;
|
||||
|
||||
return TryInsert(var_symbol);
|
||||
}
|
||||
|
||||
bool SymbolCollector::CollectMemberMethod(const ast::Method& method,
|
||||
Access access,
|
||||
Class* owner)
|
||||
{
|
||||
Signature sig = CreateSignature(method.signature);
|
||||
|
||||
auto method_symbol = factory::CreateMethod(
|
||||
method.name, method.location, sig, owner);
|
||||
|
||||
method_symbol->attributes.access = access;
|
||||
method_symbol->attributes.is_class_method = method.is_class_method;
|
||||
|
||||
// 设置 virtual/override 属性
|
||||
switch (method.modifier)
|
||||
{
|
||||
case ast::Modifier::kVirtual:
|
||||
method_symbol->attributes.is_virtual = true;
|
||||
break;
|
||||
case ast::Modifier::kOverride:
|
||||
method_symbol->attributes.is_override = true;
|
||||
break;
|
||||
case ast::Modifier::kOverload:
|
||||
method_symbol->attributes.is_overload = true;
|
||||
break;
|
||||
case ast::Modifier::kNone:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!TryInsertFunction(method_symbol, method.location))
|
||||
return false;
|
||||
|
||||
// 收集方法体
|
||||
if (method.body)
|
||||
CollectFunctionBody(method_symbol.get(), *method.body);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SymbolCollector::CollectMemberProperty(const ast::Property& property, Access access)
|
||||
{
|
||||
TypeInfo type = property.type_name ?
|
||||
TypeFactory::FromAnnotation(*property.type_name) :
|
||||
TypeInfo();
|
||||
|
||||
auto property_symbol = factory::CreateProperty(
|
||||
property.name, property.location, type);
|
||||
|
||||
property_symbol->attributes.access = access;
|
||||
property_symbol->getter = property.getter;
|
||||
property_symbol->setter = property.setter;
|
||||
|
||||
return TryInsert(property_symbol);
|
||||
}
|
||||
|
||||
bool SymbolCollector::CollectMemberConstructor(const ast::ConstructorDeclaration& ctor,
|
||||
Access access,
|
||||
Class* owner)
|
||||
{
|
||||
Signature sig = CreateSignature(ctor.signature);
|
||||
|
||||
auto ctor_symbol = factory::CreateConstructor(
|
||||
"Create", ctor.location, sig, owner);
|
||||
|
||||
ctor_symbol->attributes.access = access;
|
||||
|
||||
if (!TryInsert(ctor_symbol))
|
||||
return false;
|
||||
|
||||
// 收集构造函数体
|
||||
if (ctor.body)
|
||||
CollectConstructorBody(ctor_symbol.get(), *ctor.body);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SymbolCollector::CollectMemberDestructor(const ast::DestructorDeclaration& dtor,
|
||||
Access access,
|
||||
Class* owner)
|
||||
{
|
||||
auto dtor_symbol = factory::CreateDestructor(
|
||||
"Destroy", dtor.location, owner);
|
||||
|
||||
dtor_symbol->attributes.access = access;
|
||||
|
||||
if (!TryInsert(dtor_symbol))
|
||||
return false;
|
||||
|
||||
// 收集析构函数体
|
||||
if (dtor.body)
|
||||
CollectDestructorBody(dtor_symbol.get(), *dtor.body);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ==================== 函数体收集 ====================
|
||||
|
||||
void SymbolCollector::CollectFunctionBody(Function* func, const ast::Block& body)
|
||||
{
|
||||
// 创建函数作用域
|
||||
func->body_scope = std::make_unique<Table>(
|
||||
ScopeKind::kFunction, ctx_.CurrentScope());
|
||||
|
||||
// 进入函数作用域
|
||||
auto guard = ctx_.scope_manager.EnterScope(func->body_scope.get());
|
||||
|
||||
// 收集参数符号
|
||||
CollectFunctionParams(func);
|
||||
|
||||
// 收集函数体中的局部声明
|
||||
CollectStatements(body.statements);
|
||||
}
|
||||
|
||||
void SymbolCollector::CollectFunctionParams(Function* func)
|
||||
{
|
||||
for (const auto& param : func->signature.parameters)
|
||||
{
|
||||
auto param_symbol = factory::CreateVariable(
|
||||
param.name, Kind::kParameter, func->location, param.type);
|
||||
|
||||
param_symbol->attributes.is_var_param = param.is_var;
|
||||
param_symbol->attributes.is_out_param = param.is_out;
|
||||
|
||||
func->body_scope->Insert(param_symbol);
|
||||
}
|
||||
}
|
||||
|
||||
void SymbolCollector::CollectConstructorBody(Constructor* ctor, const ast::Block& body)
|
||||
{
|
||||
ctor->body_scope = std::make_unique<Table>(
|
||||
ScopeKind::kFunction, ctx_.CurrentScope());
|
||||
|
||||
auto guard = ctx_.scope_manager.EnterScope(ctor->body_scope.get());
|
||||
|
||||
// 收集参数
|
||||
for (const auto& param : ctor->signature.parameters)
|
||||
{
|
||||
auto param_symbol = factory::CreateVariable(
|
||||
param.name, Kind::kParameter, ctor->location, param.type);
|
||||
|
||||
param_symbol->attributes.is_var_param = param.is_var;
|
||||
param_symbol->attributes.is_out_param = param.is_out;
|
||||
|
||||
ctor->body_scope->Insert(param_symbol);
|
||||
}
|
||||
|
||||
CollectStatements(body.statements);
|
||||
}
|
||||
|
||||
void SymbolCollector::CollectDestructorBody(Destructor* dtor, const ast::Block& body)
|
||||
{
|
||||
dtor->body_scope = std::make_unique<Table>(
|
||||
ScopeKind::kFunction, ctx_.CurrentScope());
|
||||
|
||||
auto guard = ctx_.scope_manager.EnterScope(dtor->body_scope.get());
|
||||
|
||||
CollectStatements(body.statements);
|
||||
}
|
||||
|
||||
// ==================== 辅助方法 ====================
|
||||
|
||||
void SymbolCollector::CollectInScope(Table* scope,
|
||||
const std::vector<ast::ASTNode>& statements)
|
||||
{
|
||||
auto guard = ctx_.scope_manager.EnterScope(scope);
|
||||
CollectStatements(statements);
|
||||
}
|
||||
|
||||
void SymbolCollector::CollectStatements(const std::vector<ast::ASTNode>& statements)
|
||||
{
|
||||
for (const auto& stmt : statements)
|
||||
Visit(stmt);
|
||||
}
|
||||
|
||||
// ==================== 插入方法 ====================
|
||||
|
||||
bool SymbolCollector::TryInsert(SymbolPtr symbol)
|
||||
{
|
||||
if (!ctx_.CurrentScope()->Insert(symbol))
|
||||
{
|
||||
ctx_.ReportDuplicateDefinition(symbol->name, symbol->location);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SymbolCollector::TryInsertFunction(FunctionPtr func, const ast::Location& loc)
|
||||
{
|
||||
if (!ctx_.CurrentScope()->InsertFunction(func))
|
||||
{
|
||||
ctx_.ReportSignatureConflict(func->name, loc);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SymbolCollector::TryInsertUnit(UnitPtr unit)
|
||||
{
|
||||
if (!ctx_.registry.AddUnit(unit))
|
||||
{
|
||||
ctx_.ReportUnitConflict(unit->name, unit->location);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ==================== 创建签名 ====================
|
||||
|
||||
Signature SymbolCollector::CreateSignature(const ast::Signature& ast_sig)
|
||||
{
|
||||
Signature sig;
|
||||
|
||||
for (const auto& ast_param : ast_sig.parameters)
|
||||
{
|
||||
sig.parameters.push_back(CreateParameter(ast_param));
|
||||
}
|
||||
|
||||
if (ast_sig.return_type)
|
||||
sig.return_type = TypeFactory::FromAnnotation(*ast_sig.return_type);
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
Signature::Param SymbolCollector::CreateParameter(const ast::Parameter& ast_param)
|
||||
{
|
||||
Signature::Param param;
|
||||
param.name = ast_param.name;
|
||||
param.type = ast_param.type_name ?
|
||||
TypeFactory::FromAnnotation(*ast_param.type_name) :
|
||||
TypeInfo();
|
||||
param.is_var = ast_param.is_var;
|
||||
param.is_out = ast_param.is_out;
|
||||
param.default_value = ast_param.default_value;
|
||||
return param;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "../../ast/types.hpp"
|
||||
#include "./context.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
/**
|
||||
* 符号收集器 - 负责从 AST 收集符号
|
||||
*
|
||||
* 职责:
|
||||
* - 遍历 AST 节点
|
||||
* - 创建符号对象
|
||||
* - 插入作用域
|
||||
* - 管理作用域切换
|
||||
*
|
||||
* 不负责:
|
||||
* - 增量构建逻辑
|
||||
* - 缓存管理
|
||||
* - 依赖追踪
|
||||
* - 类型引用解析(保持字符串形式)
|
||||
*/
|
||||
class SymbolCollector
|
||||
{
|
||||
public:
|
||||
explicit SymbolCollector(CollectorContext& context);
|
||||
virtual ~SymbolCollector() = default;
|
||||
|
||||
// 主入口 - 收集所有节点
|
||||
bool Collect(const std::vector<ast::ASTNode>& nodes);
|
||||
|
||||
protected:
|
||||
// ==================== AST 访问 ====================
|
||||
|
||||
virtual bool Visit(const ast::ASTNode& node);
|
||||
|
||||
// ==================== 顶层声明 ====================
|
||||
|
||||
bool CollectUnit(const ast::UnitDefinition& unit);
|
||||
bool CollectGlobal(const ast::GlobalDeclaration& global);
|
||||
bool CollectStatic(const ast::StaticDeclaration& decl);
|
||||
bool CollectVariable(const ast::VarDeclaration& var);
|
||||
bool CollectConstant(const ast::ConstDeclaration& constant);
|
||||
bool CollectAssignment(const ast::AssignmentStatement& stmt);
|
||||
bool CollectFunctionDef(const ast::FunctionDefinition& func);
|
||||
bool CollectClass(const ast::ClassDefinition& class_def);
|
||||
bool CollectUsesClause(const ast::UsesClause& uses);
|
||||
|
||||
// ==================== 类成员收集 ====================
|
||||
|
||||
bool CollectClassMember(const ast::ClassMember& member, Class* owner);
|
||||
bool CollectMemberVariable(const ast::VarDeclaration& var, Access access);
|
||||
bool CollectMemberStatic(const ast::StaticDeclaration& decl, Access access);
|
||||
bool CollectMemberMethod(const ast::Method& method, Access access, Class* owner);
|
||||
bool CollectMemberProperty(const ast::Property& property, Access access);
|
||||
bool CollectMemberConstructor(const ast::ConstructorDeclaration& ctor, Access access, Class* owner);
|
||||
bool CollectMemberDestructor(const ast::DestructorDeclaration& dtor, Access access, Class* owner);
|
||||
|
||||
// ==================== 函数体收集 ====================
|
||||
|
||||
void CollectFunctionBody(Function* func, const ast::Block& body);
|
||||
void CollectFunctionParams(Function* func);
|
||||
void CollectConstructorBody(Constructor* ctor, const ast::Block& body);
|
||||
void CollectDestructorBody(Destructor* dtor, const ast::Block& body);
|
||||
|
||||
// ==================== 辅助方法 ====================
|
||||
|
||||
void CollectInScope(Table* scope, const std::vector<ast::ASTNode>& statements);
|
||||
void CollectStatements(const std::vector<ast::ASTNode>& statements);
|
||||
|
||||
// ==================== 插入方法 ====================
|
||||
|
||||
bool TryInsert(SymbolPtr symbol);
|
||||
bool TryInsertFunction(FunctionPtr func, const ast::Location& loc);
|
||||
bool TryInsertUnit(UnitPtr unit);
|
||||
|
||||
// ==================== 创建签名 ====================
|
||||
|
||||
Signature CreateSignature(const ast::Signature& ast_sig);
|
||||
Signature::Param CreateParameter(const ast::Parameter& ast_param);
|
||||
|
||||
protected:
|
||||
CollectorContext& ctx_;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
#include "./error.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
// ==================== 错误类型名称映射 ====================
|
||||
|
||||
namespace
|
||||
{
|
||||
const char* GetErrorKindName(ErrorKind kind)
|
||||
{
|
||||
static const std::unordered_map<ErrorKind, const char*> names = {
|
||||
{ ErrorKind::kDuplicateDefinition, "Duplicate definition" },
|
||||
{ ErrorKind::kSignatureConflict, "Signature conflict" },
|
||||
{ ErrorKind::kUndefinedType, "Undefined type" },
|
||||
{ ErrorKind::kInvalidAccess, "Invalid access" },
|
||||
{ ErrorKind::kCircularDependency, "Circular dependency" },
|
||||
{ ErrorKind::kInvalidOverride, "Invalid override" },
|
||||
{ ErrorKind::kInvalidTypeReference, "Invalid type reference" },
|
||||
{ ErrorKind::kMemberNotFound, "Member not found" },
|
||||
{ ErrorKind::kInvalidModifier, "Invalid modifier" },
|
||||
{ ErrorKind::kInvalidParent, "Invalid parent" },
|
||||
};
|
||||
|
||||
auto it = names.find(kind);
|
||||
return it != names.end() ? it->second : "Unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== Error 实现 ====================
|
||||
|
||||
Error::Error(ErrorKind k, const std::string& msg, const ast::Location& loc) :
|
||||
kind(k), message(msg), location(loc)
|
||||
{
|
||||
}
|
||||
|
||||
std::string Error::ToString() const
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "[" << location.start_line << ":" << location.start_column << "] ";
|
||||
oss << GetErrorKindName(kind);
|
||||
oss << ": " << message;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
Error Error::DuplicateDefinition(const std::string& name, const ast::Location& loc)
|
||||
{
|
||||
return Error(ErrorKind::kDuplicateDefinition, "Duplicate definition: " + name, loc);
|
||||
}
|
||||
|
||||
Error Error::UndefinedType(const std::string& type, const ast::Location& loc)
|
||||
{
|
||||
return Error(ErrorKind::kUndefinedType, "Undefined type: " + type, loc);
|
||||
}
|
||||
|
||||
Error Error::CircularDependency(const std::string& msg, const ast::Location& loc)
|
||||
{
|
||||
return Error(ErrorKind::kCircularDependency, msg, loc);
|
||||
}
|
||||
|
||||
// ==================== ErrorReporter 实现 ====================
|
||||
|
||||
void ErrorReporter::Report(ErrorKind kind, const std::string& msg, const ast::Location& loc)
|
||||
{
|
||||
errors_.emplace_back(kind, msg, loc);
|
||||
}
|
||||
|
||||
void ErrorReporter::Report(const Error& error)
|
||||
{
|
||||
errors_.push_back(error);
|
||||
}
|
||||
|
||||
const std::vector<Error>& ErrorReporter::GetErrors() const
|
||||
{
|
||||
return errors_;
|
||||
}
|
||||
|
||||
bool ErrorReporter::HasErrors() const
|
||||
{
|
||||
return !errors_.empty();
|
||||
}
|
||||
|
||||
size_t ErrorReporter::ErrorCount() const
|
||||
{
|
||||
return errors_.size();
|
||||
}
|
||||
|
||||
void ErrorReporter::Clear()
|
||||
{
|
||||
errors_.clear();
|
||||
}
|
||||
|
||||
void ErrorReporter::ReportDuplicateDefinition(const std::string& name, const ast::Location& loc)
|
||||
{
|
||||
Report(Error::DuplicateDefinition(name, loc));
|
||||
}
|
||||
|
||||
void ErrorReporter::ReportUndefinedType(const std::string& type, const ast::Location& loc)
|
||||
{
|
||||
Report(Error::UndefinedType(type, loc));
|
||||
}
|
||||
|
||||
void ErrorReporter::ReportCircularDependency(const std::string& msg, const ast::Location& loc)
|
||||
{
|
||||
Report(Error::CircularDependency(msg, loc));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "../../ast/types.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
enum class ErrorKind
|
||||
{
|
||||
kDuplicateDefinition,
|
||||
kSignatureConflict,
|
||||
kUndefinedType,
|
||||
kInvalidAccess,
|
||||
kCircularDependency,
|
||||
kInvalidOverride,
|
||||
kInvalidTypeReference,
|
||||
kMemberNotFound,
|
||||
kInvalidModifier,
|
||||
kInvalidParent,
|
||||
};
|
||||
|
||||
struct Error
|
||||
{
|
||||
ErrorKind kind;
|
||||
std::string message;
|
||||
ast::Location location;
|
||||
|
||||
Error(ErrorKind k, const std::string& msg, const ast::Location& loc);
|
||||
std::string ToString() const;
|
||||
|
||||
static Error DuplicateDefinition(const std::string& name, const ast::Location& loc);
|
||||
static Error UndefinedType(const std::string& type, const ast::Location& loc);
|
||||
static Error CircularDependency(const std::string& msg, const ast::Location& loc);
|
||||
};
|
||||
|
||||
class ErrorReporter
|
||||
{
|
||||
public:
|
||||
ErrorReporter() = default;
|
||||
|
||||
void Report(ErrorKind kind, const std::string& msg, const ast::Location& loc);
|
||||
void Report(const Error& error);
|
||||
|
||||
const std::vector<Error>& GetErrors() const;
|
||||
bool HasErrors() const;
|
||||
size_t ErrorCount() const;
|
||||
void Clear();
|
||||
|
||||
void ReportDuplicateDefinition(const std::string& name, const ast::Location& loc);
|
||||
void ReportUndefinedType(const std::string& type, const ast::Location& loc);
|
||||
void ReportCircularDependency(const std::string& msg, const ast::Location& loc);
|
||||
|
||||
private:
|
||||
std::vector<Error> errors_;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
#include "./registry.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
SymbolRegistry::SymbolRegistry() :
|
||||
global_scope_(ScopeKind::kGlobal, nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
// 移动构造函数
|
||||
SymbolRegistry::SymbolRegistry(SymbolRegistry&& other) noexcept :
|
||||
global_scope_(std::move(other.global_scope_)),
|
||||
units_(std::move(other.units_))
|
||||
{
|
||||
// 修复 global_scope_ 中所有符号的 scope 指针
|
||||
for (auto& [name, symbol] : global_scope_.Symbols())
|
||||
{
|
||||
if (symbol && symbol->scope == &other.global_scope_)
|
||||
{
|
||||
symbol->scope = &global_scope_;
|
||||
}
|
||||
}
|
||||
|
||||
// 修复 units_ 中所有符号的 scope 指针
|
||||
for (auto& [name, unit] : units_)
|
||||
{
|
||||
if (unit && unit->scope == &other.global_scope_)
|
||||
{
|
||||
unit->scope = &global_scope_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 移动赋值运算符
|
||||
SymbolRegistry& SymbolRegistry::operator=(SymbolRegistry&& other) noexcept
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
global_scope_ = std::move(other.global_scope_);
|
||||
units_ = std::move(other.units_);
|
||||
|
||||
// 修复 global_scope_ 中所有符号的 scope 指针
|
||||
for (auto& [name, symbol] : global_scope_.Symbols())
|
||||
{
|
||||
if (symbol && symbol->scope == &other.global_scope_)
|
||||
{
|
||||
symbol->scope = &global_scope_;
|
||||
}
|
||||
}
|
||||
|
||||
// 修复 units_ 中所有符号的 scope 指针
|
||||
for (auto& [name, unit] : units_)
|
||||
{
|
||||
if (unit && unit->scope == &other.global_scope_)
|
||||
{
|
||||
unit->scope = &global_scope_;
|
||||
}
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Table* SymbolRegistry::GlobalScope()
|
||||
{
|
||||
return &global_scope_;
|
||||
}
|
||||
|
||||
const Table* SymbolRegistry::GlobalScope() const
|
||||
{
|
||||
return &global_scope_;
|
||||
}
|
||||
|
||||
bool SymbolRegistry::AddUnit(UnitPtr unit)
|
||||
{
|
||||
if (!unit)
|
||||
return false;
|
||||
|
||||
if (units_.count(unit->name) > 0)
|
||||
return false;
|
||||
|
||||
if (!global_scope_.Insert(unit))
|
||||
return false;
|
||||
|
||||
units_[unit->name] = unit;
|
||||
return true;
|
||||
}
|
||||
|
||||
UnitPtr SymbolRegistry::FindUnit(const std::string& name) const
|
||||
{
|
||||
auto it = units_.find(name);
|
||||
if (it != units_.end())
|
||||
return it->second;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::unordered_map<std::string, UnitPtr>& SymbolRegistry::Units() const
|
||||
{
|
||||
return units_;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
#include "./symbol.hpp"
|
||||
#include "./table.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
class SymbolRegistry
|
||||
{
|
||||
public:
|
||||
SymbolRegistry();
|
||||
~SymbolRegistry() = default;
|
||||
|
||||
SymbolRegistry(const SymbolRegistry&) = delete;
|
||||
SymbolRegistry& operator=(const SymbolRegistry&) = delete;
|
||||
|
||||
// 自定义移动构造和移动赋值
|
||||
SymbolRegistry(SymbolRegistry&& other) noexcept;
|
||||
SymbolRegistry& operator=(SymbolRegistry&& other) noexcept;
|
||||
|
||||
// ==================== 访问全局作用域 ====================
|
||||
|
||||
Table* GlobalScope();
|
||||
const Table* GlobalScope() const;
|
||||
|
||||
// ==================== Unit 管理 ====================
|
||||
|
||||
bool AddUnit(UnitPtr unit);
|
||||
UnitPtr FindUnit(const std::string& name) const;
|
||||
const std::unordered_map<std::string, UnitPtr>& Units() const;
|
||||
|
||||
private:
|
||||
Table global_scope_;
|
||||
std::unordered_map<std::string, UnitPtr> units_;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
#include "./symbol.hpp"
|
||||
#include "./table.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
// ==================== Function 实现 ====================
|
||||
|
||||
Function::Function(const std::string& name, const ast::Location& loc, const Signature& sig) :
|
||||
Symbol(name, Kind::kFunction, loc), signature(sig), is_overload(false), body_scope(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
Function::~Function() = default;
|
||||
|
||||
Function::Function(Function&&) noexcept = default;
|
||||
|
||||
Function& Function::operator=(Function&&) noexcept = default;
|
||||
|
||||
// ==================== Method 实现 ====================
|
||||
|
||||
Method::Method(const std::string& name, const ast::Location& loc, const Signature& sig) :
|
||||
Function(name, loc, sig), owner_class(nullptr)
|
||||
{
|
||||
kind = Kind::kMethod;
|
||||
}
|
||||
|
||||
// ==================== Constructor 实现 ====================
|
||||
|
||||
Constructor::Constructor(const std::string& name, const ast::Location& loc, const Signature& sig) :
|
||||
Symbol(name, Kind::kConstructor, loc), signature(sig), owner_class(nullptr), body_scope(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
Constructor::~Constructor() = default;
|
||||
|
||||
Constructor::Constructor(Constructor&&) noexcept = default;
|
||||
|
||||
Constructor& Constructor::operator=(Constructor&&) noexcept = default;
|
||||
|
||||
// ==================== Destructor 实现 ====================
|
||||
|
||||
Destructor::Destructor(const std::string& name, const ast::Location& loc) :
|
||||
Symbol(name, Kind::kDestructor, loc), owner_class(nullptr), body_scope(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
Destructor::~Destructor() = default;
|
||||
|
||||
Destructor::Destructor(Destructor&&) noexcept = default;
|
||||
|
||||
Destructor& Destructor::operator=(Destructor&&) noexcept = default;
|
||||
|
||||
// ==================== Class 实现 ====================
|
||||
|
||||
Class::Class(const std::string& name, const ast::Location& loc) :
|
||||
Symbol(name, Kind::kClass, loc), members(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
Class::~Class() = default;
|
||||
|
||||
Class::Class(Class&&) noexcept = default;
|
||||
|
||||
Class& Class::operator=(Class&&) noexcept = default;
|
||||
|
||||
// ==================== Unit 实现 ====================
|
||||
|
||||
Unit::Unit(const std::string& name, const ast::Location& loc) :
|
||||
Symbol(name, Kind::kUnit, loc), interface_symbols(nullptr), implementation_symbols(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
Unit::~Unit() = default;
|
||||
|
||||
Unit::Unit(Unit&&) noexcept = default;
|
||||
|
||||
Unit& Unit::operator=(Unit&&) noexcept = default;
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
#include <memory>
|
||||
#include "../../ast/types.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
// 前向声明
|
||||
class Table;
|
||||
|
||||
// ==================== 基本枚举 ====================
|
||||
|
||||
enum class Kind
|
||||
{
|
||||
kVariable,
|
||||
kStaticVariable,
|
||||
kGlobalVariable,
|
||||
kConstant,
|
||||
kParameter,
|
||||
kFunction,
|
||||
kClass,
|
||||
kMethod,
|
||||
kConstructor,
|
||||
kDestructor,
|
||||
kProperty,
|
||||
kUnit,
|
||||
};
|
||||
|
||||
enum class ScopeKind
|
||||
{
|
||||
kGlobal,
|
||||
kUnit,
|
||||
kInterface,
|
||||
kImplementation,
|
||||
kFunction,
|
||||
kClass,
|
||||
kBlock,
|
||||
};
|
||||
|
||||
using Access = ast::Access;
|
||||
|
||||
// ==================== 符号属性 ====================
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
bool is_const = false;
|
||||
bool is_static = false;
|
||||
bool is_var_param = false;
|
||||
bool is_out_param = false;
|
||||
Access access = Access::kPublic;
|
||||
bool is_virtual = false;
|
||||
bool is_override = false;
|
||||
bool is_overload = false;
|
||||
bool is_class_method = false;
|
||||
};
|
||||
|
||||
// ==================== 类型信息(纯数据) ====================
|
||||
class TypeInfo
|
||||
{
|
||||
public:
|
||||
TypeInfo() = default;
|
||||
|
||||
explicit TypeInfo(const std::string& annotation) :
|
||||
annotation_(annotation) {}
|
||||
|
||||
bool HasAnnotation() const { return !annotation_.empty(); }
|
||||
const std::string& Annotation() const { return annotation_; }
|
||||
// bool IsArray() const;
|
||||
// bool IsPrimitive() const;
|
||||
|
||||
private:
|
||||
std::string annotation_; // 类型注解(原始字符串)
|
||||
};
|
||||
|
||||
// ==================== 函数签名(纯数据) ====================
|
||||
|
||||
class Signature
|
||||
{
|
||||
public:
|
||||
size_t ParamCount() const { return parameters.size(); }
|
||||
bool HasReturnType() const { return return_type.has_value(); }
|
||||
|
||||
public:
|
||||
struct Param
|
||||
{
|
||||
std::string name;
|
||||
TypeInfo type;
|
||||
bool is_var = false;
|
||||
bool is_out = false;
|
||||
std::optional<std::string> default_value;
|
||||
};
|
||||
|
||||
std::vector<Param> parameters;
|
||||
std::optional<TypeInfo> return_type;
|
||||
};
|
||||
|
||||
// ==================== 符号基类 ====================
|
||||
|
||||
class Symbol
|
||||
{
|
||||
public:
|
||||
Symbol(const std::string& name, Kind kind, const ast::Location& loc) :
|
||||
name(name), kind(kind), location(loc), scope(nullptr)
|
||||
{
|
||||
}
|
||||
virtual ~Symbol() = default;
|
||||
Symbol(const Symbol&) = delete;
|
||||
Symbol& operator=(const Symbol&) = delete;
|
||||
Symbol(Symbol&&) noexcept = default;
|
||||
Symbol& operator=(Symbol&&) noexcept = default;
|
||||
|
||||
public:
|
||||
std::string name;
|
||||
Kind kind;
|
||||
ast::Location location;
|
||||
Table* scope;
|
||||
Attributes attributes;
|
||||
};
|
||||
|
||||
// ==================== 具体符号类 ====================
|
||||
|
||||
class Variable : public Symbol
|
||||
{
|
||||
public:
|
||||
Variable(const std::string& name, Kind kind, const ast::Location& loc, const TypeInfo& type) :
|
||||
Symbol(name, kind, loc), type(type)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
TypeInfo type;
|
||||
std::optional<std::string> initialization_expr;
|
||||
};
|
||||
|
||||
class Constant : public Symbol
|
||||
{
|
||||
public:
|
||||
Constant(const std::string& name, const ast::Location& loc, const TypeInfo& type, const std::string& value) :
|
||||
Symbol(name, Kind::kConstant, loc), type(type), value(value)
|
||||
{
|
||||
attributes.is_const = true;
|
||||
}
|
||||
|
||||
public:
|
||||
TypeInfo type;
|
||||
std::string value;
|
||||
};
|
||||
|
||||
class Function : public Symbol
|
||||
{
|
||||
public:
|
||||
Function(const std::string& name, const ast::Location& loc, const Signature& sig);
|
||||
~Function() override;
|
||||
Function(const Function&) = delete;
|
||||
Function& operator=(const Function&) = delete;
|
||||
Function(Function&&) noexcept;
|
||||
Function& operator=(Function&&) noexcept;
|
||||
|
||||
public:
|
||||
Signature signature;
|
||||
bool is_overload;
|
||||
std::unique_ptr<Table> body_scope;
|
||||
};
|
||||
|
||||
class Method : public Function
|
||||
{
|
||||
public:
|
||||
Method(const std::string& name, const ast::Location& loc, const Signature& sig);
|
||||
|
||||
public:
|
||||
class Class* owner_class;
|
||||
std::optional<ast::Location> implementation_location;
|
||||
};
|
||||
|
||||
class Constructor : public Symbol
|
||||
{
|
||||
public:
|
||||
Signature signature;
|
||||
class Class* owner_class;
|
||||
std::unique_ptr<Table> body_scope;
|
||||
|
||||
Constructor(const std::string& name, const ast::Location& loc, const Signature& sig);
|
||||
|
||||
~Constructor() override;
|
||||
|
||||
Constructor(const Constructor&) = delete;
|
||||
Constructor& operator=(const Constructor&) = delete;
|
||||
Constructor(Constructor&&) noexcept;
|
||||
Constructor& operator=(Constructor&&) noexcept;
|
||||
};
|
||||
|
||||
class Destructor : public Symbol
|
||||
{
|
||||
public:
|
||||
class Class* owner_class;
|
||||
std::unique_ptr<Table> body_scope;
|
||||
|
||||
Destructor(const std::string& name, const ast::Location& loc);
|
||||
|
||||
~Destructor() override;
|
||||
|
||||
Destructor(const Destructor&) = delete;
|
||||
Destructor& operator=(const Destructor&) = delete;
|
||||
Destructor(Destructor&&) noexcept;
|
||||
Destructor& operator=(Destructor&&) noexcept;
|
||||
};
|
||||
|
||||
class Property : public Symbol
|
||||
{
|
||||
public:
|
||||
TypeInfo type;
|
||||
std::optional<std::string> getter;
|
||||
std::optional<std::string> setter;
|
||||
|
||||
Property(const std::string& name, const ast::Location& loc, const TypeInfo& type) :
|
||||
Symbol(name, Kind::kProperty, loc), type(type)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class Class : public Symbol
|
||||
{
|
||||
public:
|
||||
std::vector<std::string> parent_names;
|
||||
std::vector<Class*> parents;
|
||||
std::unique_ptr<Table> members;
|
||||
|
||||
Class(const std::string& name, const ast::Location& loc);
|
||||
|
||||
~Class() override;
|
||||
|
||||
Class(const Class&) = delete;
|
||||
Class& operator=(const Class&) = delete;
|
||||
Class(Class&&) noexcept;
|
||||
Class& operator=(Class&&) noexcept;
|
||||
};
|
||||
|
||||
class Unit : public Symbol
|
||||
{
|
||||
public:
|
||||
std::vector<std::string> uses;
|
||||
std::unique_ptr<Table> interface_symbols;
|
||||
std::unique_ptr<Table> implementation_symbols;
|
||||
|
||||
Unit(const std::string& name, const ast::Location& loc);
|
||||
|
||||
~Unit() override;
|
||||
|
||||
Unit(const Unit&) = delete;
|
||||
Unit& operator=(const Unit&) = delete;
|
||||
Unit(Unit&&) noexcept;
|
||||
Unit& operator=(Unit&&) noexcept;
|
||||
};
|
||||
|
||||
// ==================== 智能指针类型别名 ====================
|
||||
|
||||
using SymbolPtr = std::shared_ptr<Symbol>;
|
||||
using VariablePtr = std::shared_ptr<Variable>;
|
||||
using ConstantPtr = std::shared_ptr<Constant>;
|
||||
using FunctionPtr = std::shared_ptr<Function>;
|
||||
using MethodPtr = std::shared_ptr<Method>;
|
||||
using ConstructorPtr = std::shared_ptr<Constructor>;
|
||||
using DestructorPtr = std::shared_ptr<Destructor>;
|
||||
using PropertyPtr = std::shared_ptr<Property>;
|
||||
using ClassPtr = std::shared_ptr<Class>;
|
||||
using UnitPtr = std::shared_ptr<Unit>;
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
#include "./table.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
// ==================== LookupResult 实现 ====================
|
||||
|
||||
LookupResult LookupResult::Found(Symbol* sym, Table* scp)
|
||||
{
|
||||
LookupResult result;
|
||||
result.symbol = sym;
|
||||
result.scope = scp;
|
||||
result.success = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
LookupResult LookupResult::NotFound()
|
||||
{
|
||||
return LookupResult{};
|
||||
}
|
||||
|
||||
LookupResult::operator bool() const
|
||||
{
|
||||
return success;
|
||||
}
|
||||
|
||||
// ==================== Table 实现 ====================
|
||||
|
||||
Table::Table(ScopeKind kind, Table* parent) :
|
||||
kind_(kind), parent_(parent)
|
||||
{
|
||||
}
|
||||
|
||||
ScopeKind Table::Kind() const
|
||||
{
|
||||
return kind_;
|
||||
}
|
||||
|
||||
Table* Table::Parent() const
|
||||
{
|
||||
return parent_;
|
||||
}
|
||||
|
||||
const std::unordered_map<std::string, SymbolPtr>& Table::Symbols() const
|
||||
{
|
||||
return symbols_;
|
||||
}
|
||||
|
||||
const std::unordered_map<std::string, std::vector<FunctionPtr>>& Table::OverloadedFunctions() const
|
||||
{
|
||||
return overloaded_functions_;
|
||||
}
|
||||
|
||||
Table* Table::CreateChild(ScopeKind kind)
|
||||
{
|
||||
auto child = std::make_unique<Table>(kind, this);
|
||||
Table* ptr = child.get();
|
||||
children_.push_back(std::move(child));
|
||||
return ptr;
|
||||
}
|
||||
|
||||
bool Table::Insert(SymbolPtr symbol)
|
||||
{
|
||||
if (!symbol)
|
||||
return false;
|
||||
|
||||
if (symbols_.count(symbol->name) > 0)
|
||||
return false;
|
||||
|
||||
symbol->scope = this;
|
||||
symbols_[symbol->name] = symbol;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Table::InsertFunction(FunctionPtr func)
|
||||
{
|
||||
if (!func)
|
||||
return false;
|
||||
|
||||
func->scope = this;
|
||||
|
||||
auto& overloads = overloaded_functions_[func->name];
|
||||
|
||||
if (func->is_overload)
|
||||
overloads.push_back(func);
|
||||
|
||||
if (overloads.size() == 1)
|
||||
symbols_[func->name] = func;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
LookupResult Table::LookupLocal(const std::string& name) const
|
||||
{
|
||||
auto it = symbols_.find(name);
|
||||
if (it != symbols_.end())
|
||||
return LookupResult::Found(it->second.get(), const_cast<Table*>(this));
|
||||
return LookupResult::NotFound();
|
||||
}
|
||||
|
||||
LookupResult Table::Lookup(const std::string& name) const
|
||||
{
|
||||
auto result = LookupLocal(name);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
if (parent_)
|
||||
return parent_->Lookup(name);
|
||||
|
||||
return LookupResult::NotFound();
|
||||
}
|
||||
|
||||
std::vector<FunctionPtr> Table::LookupOverloads(const std::string& name) const
|
||||
{
|
||||
auto it = overloaded_functions_.find(name);
|
||||
if (it != overloaded_functions_.end())
|
||||
return it->second;
|
||||
|
||||
if (parent_)
|
||||
return parent_->LookupOverloads(name);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
MethodPtr Table::FindMethodInClass(const std::string& class_name, const std::string& method_name) const
|
||||
{
|
||||
// 1. 查找类符号
|
||||
auto class_result = Lookup(class_name);
|
||||
if (!class_result || class_result.symbol->kind != Kind::kClass)
|
||||
return nullptr;
|
||||
|
||||
auto class_sym = static_cast<Class*>(class_result.symbol);
|
||||
if (!class_sym->members)
|
||||
return nullptr;
|
||||
|
||||
auto method_result = class_sym->members->LookupLocal(method_name);
|
||||
if (!method_result || method_result.symbol->kind != Kind::kMethod)
|
||||
return nullptr;
|
||||
|
||||
auto it = class_sym->members->Symbols().find(method_name);
|
||||
if (it != class_sym->members->Symbols().end())
|
||||
return std::static_pointer_cast<Method>(it->second);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include "./symbol.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
// ==================== 查找结果 ====================
|
||||
|
||||
struct LookupResult
|
||||
{
|
||||
Symbol* symbol = nullptr;
|
||||
Table* scope = nullptr;
|
||||
bool success = false;
|
||||
|
||||
static LookupResult Found(Symbol* sym, Table* scp);
|
||||
static LookupResult NotFound();
|
||||
|
||||
explicit operator bool() const;
|
||||
};
|
||||
|
||||
// ==================== 符号表 / 作用域 ====================
|
||||
|
||||
class Table
|
||||
{
|
||||
public:
|
||||
explicit Table(ScopeKind kind, Table* parent = nullptr);
|
||||
~Table() = default;
|
||||
|
||||
Table(const Table&) = delete;
|
||||
Table& operator=(const Table&) = delete;
|
||||
Table(Table&&) noexcept = default;
|
||||
Table& operator=(Table&&) noexcept = default;
|
||||
|
||||
// ==================== 访问器 ====================
|
||||
|
||||
ScopeKind Kind() const;
|
||||
Table* Parent() const;
|
||||
const std::unordered_map<std::string, SymbolPtr>& Symbols() const;
|
||||
const std::unordered_map<std::string, std::vector<FunctionPtr>>& OverloadedFunctions() const;
|
||||
|
||||
// ==================== 作用域管理 ====================
|
||||
|
||||
Table* CreateChild(ScopeKind kind);
|
||||
|
||||
// ==================== 符号插入(核心方法) ====================
|
||||
|
||||
bool Insert(SymbolPtr symbol);
|
||||
bool InsertFunction(FunctionPtr func);
|
||||
|
||||
// ==================== 符号查找 ====================
|
||||
|
||||
LookupResult LookupLocal(const std::string& name) const;
|
||||
LookupResult Lookup(const std::string& name) const;
|
||||
|
||||
// 优化:返回 vector 引用或空 vector
|
||||
std::vector<FunctionPtr> LookupOverloads(const std::string& name) const;
|
||||
MethodPtr FindMethodInClass(const std::string& class_name, const std::string& method_name) const;
|
||||
|
||||
private:
|
||||
ScopeKind kind_;
|
||||
Table* parent_;
|
||||
std::vector<std::unique_ptr<Table>> children_;
|
||||
std::unordered_map<std::string, SymbolPtr> symbols_;
|
||||
std::unordered_map<std::string, std::vector<FunctionPtr>> overloaded_functions_;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
#include "../utils/type.hpp"
|
||||
#include "./factory.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
// ==================== 创建符号对象 ====================
|
||||
|
||||
VariablePtr factory::CreateVariable(
|
||||
const std::string& name,
|
||||
Kind kind,
|
||||
const ast::Location& loc,
|
||||
const TypeInfo& type)
|
||||
{
|
||||
return std::make_shared<Variable>(name, kind, loc, type);
|
||||
}
|
||||
|
||||
ConstantPtr factory::CreateConstant(
|
||||
const std::string& name,
|
||||
const ast::Location& loc,
|
||||
const TypeInfo& type,
|
||||
const std::string& value)
|
||||
{
|
||||
return std::make_shared<Constant>(name, loc, type, value);
|
||||
}
|
||||
|
||||
FunctionPtr factory::CreateFunction(
|
||||
const std::string& name,
|
||||
const ast::Location& loc,
|
||||
const Signature& sig)
|
||||
{
|
||||
return std::make_shared<Function>(name, loc, sig);
|
||||
}
|
||||
|
||||
MethodPtr factory::CreateMethod(
|
||||
const std::string& name,
|
||||
const ast::Location& loc,
|
||||
const Signature& sig,
|
||||
Class* owner)
|
||||
{
|
||||
auto method = std::make_shared<Method>(name, loc, sig);
|
||||
method->owner_class = owner;
|
||||
return method;
|
||||
}
|
||||
|
||||
ConstructorPtr factory::CreateConstructor(
|
||||
const std::string& name,
|
||||
const ast::Location& loc,
|
||||
const Signature& sig,
|
||||
Class* owner)
|
||||
{
|
||||
auto ctor = std::make_shared<Constructor>(name, loc, sig);
|
||||
ctor->owner_class = owner;
|
||||
return ctor;
|
||||
}
|
||||
|
||||
DestructorPtr factory::CreateDestructor(
|
||||
const std::string& name,
|
||||
const ast::Location& loc,
|
||||
Class* owner)
|
||||
{
|
||||
auto dtor = std::make_shared<Destructor>(name, loc);
|
||||
dtor->owner_class = owner;
|
||||
return dtor;
|
||||
}
|
||||
|
||||
PropertyPtr factory::CreateProperty(
|
||||
const std::string& name,
|
||||
const ast::Location& loc,
|
||||
const TypeInfo& type)
|
||||
{
|
||||
return std::make_shared<Property>(name, loc, type);
|
||||
}
|
||||
|
||||
ClassPtr factory::CreateClass(
|
||||
const std::string& name,
|
||||
const ast::Location& loc)
|
||||
{
|
||||
return std::make_shared<Class>(name, loc);
|
||||
}
|
||||
|
||||
UnitPtr factory::CreateUnit(
|
||||
const std::string& name,
|
||||
const ast::Location& loc)
|
||||
{
|
||||
return std::make_shared<Unit>(name, loc);
|
||||
}
|
||||
|
||||
// ==================== 便捷方法 ====================
|
||||
|
||||
VariablePtr factory::CreateAndInsert(
|
||||
Table* table,
|
||||
const std::string& name,
|
||||
Kind kind,
|
||||
const ast::Location& loc,
|
||||
const TypeInfo& type)
|
||||
{
|
||||
auto var = CreateVariable(name, kind, loc, type);
|
||||
if (table && table->Insert(var))
|
||||
return var;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VariablePtr factory::CreateVariableFromAST(
|
||||
const std::string& name,
|
||||
Kind kind,
|
||||
const ast::Location& loc,
|
||||
const std::optional<std::string>& type_str)
|
||||
{
|
||||
TypeInfo type = type_str ?
|
||||
TypeFactory::FromAnnotation(*type_str) :
|
||||
TypeInfo();
|
||||
return CreateVariable(name, kind, loc, type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include "../../ast/types.hpp"
|
||||
#include "../core/symbol.hpp"
|
||||
#include "../core/table.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
/**
|
||||
* 符号工厂 - 创建符号对象
|
||||
*
|
||||
* 职责:
|
||||
* - 提供符号对象的创建接口
|
||||
* - 封装 std::make_shared 调用
|
||||
*
|
||||
* 不负责:
|
||||
* - AST 到 Symbol 的转换逻辑(属于 Collector)
|
||||
*/
|
||||
namespace factory
|
||||
{
|
||||
// ==================== 创建符号对象 ====================
|
||||
|
||||
/**
|
||||
* 创建变量符号
|
||||
*/
|
||||
VariablePtr CreateVariable(
|
||||
const std::string& name,
|
||||
Kind kind,
|
||||
const ast::Location& loc,
|
||||
const TypeInfo& type);
|
||||
|
||||
/**
|
||||
* 创建常量符号
|
||||
*/
|
||||
ConstantPtr CreateConstant(
|
||||
const std::string& name,
|
||||
const ast::Location& loc,
|
||||
const TypeInfo& type,
|
||||
const std::string& value);
|
||||
|
||||
/**
|
||||
* 创建函数符号
|
||||
*/
|
||||
FunctionPtr CreateFunction(
|
||||
const std::string& name,
|
||||
const ast::Location& loc,
|
||||
const Signature& sig);
|
||||
|
||||
/**
|
||||
* 创建方法符号
|
||||
*/
|
||||
MethodPtr CreateMethod(
|
||||
const std::string& name,
|
||||
const ast::Location& loc,
|
||||
const Signature& sig,
|
||||
Class* owner);
|
||||
|
||||
/**
|
||||
* 创建构造函数符号
|
||||
*/
|
||||
ConstructorPtr CreateConstructor(
|
||||
const std::string& name,
|
||||
const ast::Location& loc,
|
||||
const Signature& sig,
|
||||
Class* owner);
|
||||
|
||||
/**
|
||||
* 创建析构函数符号
|
||||
*/
|
||||
DestructorPtr CreateDestructor(
|
||||
const std::string& name,
|
||||
const ast::Location& loc,
|
||||
Class* owner);
|
||||
|
||||
/**
|
||||
* 创建属性符号
|
||||
*/
|
||||
PropertyPtr CreateProperty(
|
||||
const std::string& name,
|
||||
const ast::Location& loc,
|
||||
const TypeInfo& type);
|
||||
|
||||
/**
|
||||
* 创建类符号
|
||||
*/
|
||||
ClassPtr CreateClass(
|
||||
const std::string& name,
|
||||
const ast::Location& loc);
|
||||
|
||||
/**
|
||||
* 创建 Unit 符号
|
||||
*/
|
||||
UnitPtr CreateUnit(const std::string& name, const ast::Location& loc);
|
||||
|
||||
// ==================== 便捷方法 ====================
|
||||
|
||||
/**
|
||||
* 创建并插入变量
|
||||
* @return 如果插入成功返回符号,否则返回 nullptr
|
||||
*/
|
||||
VariablePtr CreateAndInsert(Table* table, const std::string& name, Kind kind, const ast::Location& loc, const TypeInfo& type);
|
||||
|
||||
/**
|
||||
* 从 AST 类型字符串创建变量
|
||||
*/
|
||||
VariablePtr CreateVariableFromAST(const std::string& name, Kind kind, const ast::Location& loc,
|
||||
const std::optional<std::string>& type_str);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
#include "./scope_manager.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
// ==================== ScopeGuard 实现 ====================
|
||||
|
||||
ScopeGuard::ScopeGuard(Table*& current, Table* new_scope) :
|
||||
current_(current), previous_(current), active_(true)
|
||||
{
|
||||
current_ = new_scope;
|
||||
}
|
||||
|
||||
ScopeGuard::~ScopeGuard()
|
||||
{
|
||||
if (active_)
|
||||
{
|
||||
current_ = previous_;
|
||||
}
|
||||
}
|
||||
|
||||
ScopeGuard::ScopeGuard(ScopeGuard&& other) noexcept :
|
||||
current_(other.current_),
|
||||
previous_(other.previous_),
|
||||
active_(other.active_)
|
||||
{
|
||||
other.active_ = false;
|
||||
}
|
||||
|
||||
ScopeGuard& ScopeGuard::operator=(ScopeGuard&& other) noexcept
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
if (active_)
|
||||
{
|
||||
current_ = previous_;
|
||||
}
|
||||
|
||||
current_ = other.current_;
|
||||
previous_ = other.previous_;
|
||||
active_ = other.active_;
|
||||
|
||||
other.active_ = false;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ==================== ScopeManager 实现 ====================
|
||||
|
||||
ScopeManager::ScopeManager(Table* root) :
|
||||
root_(root), current_(root)
|
||||
{
|
||||
}
|
||||
|
||||
Table* ScopeManager::Current() const
|
||||
{
|
||||
return current_;
|
||||
}
|
||||
|
||||
ScopeGuard ScopeManager::EnterScope(Table* scope)
|
||||
{
|
||||
return ScopeGuard(current_, scope);
|
||||
}
|
||||
|
||||
ScopeGuard ScopeManager::CreateAndEnterChild(ScopeKind kind)
|
||||
{
|
||||
Table* child = current_->CreateChild(kind);
|
||||
return ScopeGuard(current_, child);
|
||||
}
|
||||
|
||||
void ScopeManager::SetCurrent(Table* scope)
|
||||
{
|
||||
current_ = scope;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
#include "../core/table.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
// ==================== 作用域守卫 ====================
|
||||
// RAII风格的作用域管理
|
||||
|
||||
class ScopeGuard
|
||||
{
|
||||
public:
|
||||
ScopeGuard(Table*& current, Table* new_scope);
|
||||
~ScopeGuard();
|
||||
|
||||
ScopeGuard(const ScopeGuard&) = delete;
|
||||
ScopeGuard& operator=(const ScopeGuard&) = delete;
|
||||
ScopeGuard(ScopeGuard&& other) noexcept;
|
||||
ScopeGuard& operator=(ScopeGuard&& other) noexcept;
|
||||
|
||||
private:
|
||||
Table*& current_;
|
||||
Table* previous_;
|
||||
bool active_;
|
||||
};
|
||||
|
||||
// ==================== 作用域管理器 ====================
|
||||
// 负责管理当前作用域的切换和导航
|
||||
|
||||
class ScopeManager
|
||||
{
|
||||
public:
|
||||
explicit ScopeManager(Table* root);
|
||||
|
||||
// 获取当前作用域
|
||||
Table* Current() const;
|
||||
|
||||
// 进入指定作用域(返回守卫,自动恢复)
|
||||
[[nodiscard]] ScopeGuard EnterScope(Table* scope);
|
||||
|
||||
// 创建子作用域并进入
|
||||
[[nodiscard]] ScopeGuard CreateAndEnterChild(ScopeKind kind);
|
||||
|
||||
// 直接设置当前作用域(不推荐,破坏RAII)
|
||||
void SetCurrent(Table* scope);
|
||||
|
||||
// 获取根作用域
|
||||
Table* Root() const { return root_; }
|
||||
|
||||
private:
|
||||
Table* root_;
|
||||
Table* current_;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
#include <sstream>
|
||||
#include "./incremental.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
// ==================== SymbolCacheKey 实现 ====================
|
||||
|
||||
std::string SymbolCacheKey::ComputeSignatureHash(const Signature& sig)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
|
||||
oss << sig.parameters.size() << "|";
|
||||
for (const auto& param : sig.parameters)
|
||||
{
|
||||
oss << param.name << ":"
|
||||
<< param.type.Annotation() << ":"
|
||||
<< (param.is_var ? "v" : "")
|
||||
<< (param.is_out ? "o" : "") << "|";
|
||||
}
|
||||
|
||||
if (sig.return_type)
|
||||
{
|
||||
oss << "ret:" << sig.return_type->Annotation();
|
||||
}
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
// ==================== SymbolCache 实现 ====================
|
||||
|
||||
SymbolCache::SymbolCache(size_t max_size) :
|
||||
max_size_(max_size)
|
||||
{
|
||||
}
|
||||
|
||||
const SymbolPtr* SymbolCache::Find(const SymbolCacheKey& key)
|
||||
{
|
||||
auto it = cache_.find(key);
|
||||
if (it != cache_.end())
|
||||
{
|
||||
// 更新 LRU:移到最前面
|
||||
TouchKey(key);
|
||||
return &it->second.symbol;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SymbolCache::Insert(const SymbolCacheKey& key, const SymbolPtr& symbol)
|
||||
{
|
||||
// 检查是否已存在
|
||||
auto it = cache_.find(key);
|
||||
if (it != cache_.end())
|
||||
{
|
||||
// 更新现有条目
|
||||
it->second.symbol = symbol;
|
||||
TouchKey(key);
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否需要淘汰
|
||||
if (cache_.size() >= max_size_)
|
||||
{
|
||||
EvictLRU();
|
||||
}
|
||||
|
||||
// 插入新条目
|
||||
lru_list_.push_front(key);
|
||||
cache_[key] = CacheEntry{ symbol, lru_list_.begin() };
|
||||
}
|
||||
|
||||
void SymbolCache::Clear()
|
||||
{
|
||||
cache_.clear();
|
||||
lru_list_.clear();
|
||||
}
|
||||
|
||||
void SymbolCache::EvictLRU()
|
||||
{
|
||||
if (lru_list_.empty())
|
||||
return;
|
||||
|
||||
// 删除最久未使用的项(列表末尾)
|
||||
auto lru_key = lru_list_.back();
|
||||
lru_list_.pop_back();
|
||||
cache_.erase(lru_key);
|
||||
}
|
||||
|
||||
void SymbolCache::TouchKey(const SymbolCacheKey& key)
|
||||
{
|
||||
auto it = cache_.find(key);
|
||||
if (it == cache_.end())
|
||||
return;
|
||||
|
||||
// 从当前位置删除
|
||||
lru_list_.erase(it->second.lru_iter);
|
||||
|
||||
// 移到最前面
|
||||
lru_list_.push_front(key);
|
||||
it->second.lru_iter = lru_list_.begin();
|
||||
}
|
||||
|
||||
SymbolCacheKey SymbolCache::MakeKey(const Symbol* symbol)
|
||||
{
|
||||
if (!symbol)
|
||||
return SymbolCacheKey{};
|
||||
|
||||
SymbolCacheKey key;
|
||||
key.symbol_name = symbol->name;
|
||||
key.symbol_kind = symbol->kind;
|
||||
key.declaration_line = symbol->location.start_line;
|
||||
key.declaration_column = symbol->location.start_column;
|
||||
|
||||
// 对于函数,添加签名哈希
|
||||
if (auto* func = dynamic_cast<const Function*>(symbol))
|
||||
{
|
||||
key.signature_hash = SymbolCacheKey::ComputeSignatureHash(func->signature);
|
||||
}
|
||||
else if (auto* ctor = dynamic_cast<const Constructor*>(symbol))
|
||||
{
|
||||
key.signature_hash = SymbolCacheKey::ComputeSignatureHash(ctor->signature);
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
SymbolCacheKey SymbolCache::MakeKeyFromAST(
|
||||
const std::string& name,
|
||||
Kind kind,
|
||||
const ast::Location& name_location,
|
||||
const std::optional<Signature>& signature)
|
||||
{
|
||||
SymbolCacheKey key;
|
||||
key.symbol_name = name;
|
||||
key.symbol_kind = kind;
|
||||
key.declaration_line = name_location.start_line;
|
||||
key.declaration_column = name_location.start_column;
|
||||
|
||||
if (signature)
|
||||
{
|
||||
key.signature_hash = SymbolCacheKey::ComputeSignatureHash(*signature);
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
#pragma once
|
||||
#include <unordered_map>
|
||||
#include <optional>
|
||||
#include <list>
|
||||
#include "../core/symbol.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
// ==================== 改进的缓存键设计 ====================
|
||||
// 基于 AST 位置和内容,避免指针地址依赖
|
||||
|
||||
struct SymbolCacheKey
|
||||
{
|
||||
std::string symbol_name;
|
||||
Kind symbol_kind;
|
||||
uint32_t declaration_line; // 使用声明位置行号
|
||||
uint32_t declaration_column; // 使用声明位置列号
|
||||
std::optional<std::string> signature_hash; // 函数签名哈希
|
||||
|
||||
bool operator==(const SymbolCacheKey& other) const
|
||||
{
|
||||
return symbol_name == other.symbol_name &&
|
||||
symbol_kind == other.symbol_kind &&
|
||||
declaration_line == other.declaration_line &&
|
||||
declaration_column == other.declaration_column &&
|
||||
signature_hash == other.signature_hash;
|
||||
}
|
||||
|
||||
// 生成签名哈希(用于函数/方法)
|
||||
static std::string ComputeSignatureHash(const Signature& sig);
|
||||
};
|
||||
|
||||
struct SymbolCacheKeyHash
|
||||
{
|
||||
size_t operator()(const SymbolCacheKey& key) const
|
||||
{
|
||||
size_t h1 = std::hash<std::string>()(key.symbol_name);
|
||||
size_t h2 = std::hash<int>()(static_cast<int>(key.symbol_kind));
|
||||
size_t h3 = std::hash<uint32_t>()(key.declaration_line);
|
||||
size_t h4 = std::hash<uint32_t>()(key.declaration_column);
|
||||
size_t h5 = key.signature_hash ?
|
||||
std::hash<std::string>()(*key.signature_hash) :
|
||||
0;
|
||||
|
||||
return h1 ^ (h2 << 1) ^ (h3 << 2) ^ (h4 << 3) ^ (h5 << 4);
|
||||
}
|
||||
};
|
||||
|
||||
// ==================== 符号缓存管理器(带LRU) ====================
|
||||
|
||||
class SymbolCache
|
||||
{
|
||||
public:
|
||||
explicit SymbolCache(size_t max_size = 10000);
|
||||
|
||||
// 查找缓存
|
||||
const SymbolPtr* Find(const SymbolCacheKey& key);
|
||||
|
||||
// 插入缓存
|
||||
void Insert(const SymbolCacheKey& key, const SymbolPtr& symbol);
|
||||
|
||||
// 清空缓存
|
||||
void Clear();
|
||||
|
||||
// 获取缓存大小
|
||||
size_t Size() const { return cache_.size(); }
|
||||
|
||||
// 设置最大缓存大小
|
||||
void SetMaxSize(size_t max_size) { max_size_ = max_size; }
|
||||
|
||||
// 从 Symbol 生成 Key
|
||||
static SymbolCacheKey MakeKey(const Symbol* symbol);
|
||||
|
||||
// 从 AST 信息生成 Key
|
||||
static SymbolCacheKey MakeKeyFromAST(
|
||||
const std::string& name,
|
||||
Kind kind,
|
||||
const ast::Location& name_location,
|
||||
const std::optional<Signature>& signature = std::nullopt);
|
||||
|
||||
private:
|
||||
// LRU 淘汰策略
|
||||
void EvictLRU();
|
||||
void TouchKey(const SymbolCacheKey& key);
|
||||
|
||||
private:
|
||||
struct CacheEntry
|
||||
{
|
||||
SymbolPtr symbol;
|
||||
std::list<SymbolCacheKey>::iterator lru_iter;
|
||||
};
|
||||
|
||||
std::unordered_map<SymbolCacheKey, CacheEntry, SymbolCacheKeyHash> cache_;
|
||||
std::list<SymbolCacheKey> lru_list_; // 最近使用列表
|
||||
size_t max_size_;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,344 @@
|
||||
#include "../core/symbol.hpp"
|
||||
#include "./incremental_engine.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
IncrementalEngine::IncrementalEngine() :
|
||||
cache_(10000),
|
||||
max_cache_size_(10000)
|
||||
{
|
||||
}
|
||||
|
||||
// ==================== 符号复用与缓存 ====================
|
||||
|
||||
bool IncrementalEngine::TryReuseSymbol(const ast::ASTNode& node, Table* scope, SymbolRegistry* registry)
|
||||
{
|
||||
return std::visit([this, scope, registry](auto&& arg) -> bool {
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
|
||||
if constexpr (std::is_same_v<T, std::monostate>)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, ast::VarDeclaration>)
|
||||
{
|
||||
auto key = SymbolCache::MakeKeyFromAST(
|
||||
arg.name, Kind::kVariable, arg.name_location);
|
||||
const SymbolPtr* cached = cache_.Find(key);
|
||||
|
||||
if (cached && *cached)
|
||||
{
|
||||
return scope->Insert(*cached);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, ast::GlobalDeclaration>)
|
||||
{
|
||||
auto key = SymbolCache::MakeKeyFromAST(
|
||||
arg.name, Kind::kGlobalVariable, arg.name_location);
|
||||
const SymbolPtr* cached = cache_.Find(key);
|
||||
|
||||
if (cached && *cached)
|
||||
{
|
||||
return scope->Insert(*cached);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, ast::StaticDeclaration>)
|
||||
{
|
||||
auto key = SymbolCache::MakeKeyFromAST(
|
||||
arg.name, Kind::kStaticVariable, arg.name_location);
|
||||
const SymbolPtr* cached = cache_.Find(key);
|
||||
|
||||
if (cached && *cached)
|
||||
{
|
||||
return scope->Insert(*cached);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, ast::ConstDeclaration>)
|
||||
{
|
||||
auto key = SymbolCache::MakeKeyFromAST(
|
||||
arg.name, Kind::kConstant, arg.name_location);
|
||||
const SymbolPtr* cached = cache_.Find(key);
|
||||
|
||||
if (cached && *cached)
|
||||
{
|
||||
return scope->Insert(*cached);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, ast::FunctionDefinition>)
|
||||
{
|
||||
// 创建签名用于缓存键
|
||||
Signature sig;
|
||||
for (const auto& param : arg.signature.parameters)
|
||||
{
|
||||
Signature::Param p;
|
||||
p.name = param.name;
|
||||
if (param.type_name)
|
||||
{
|
||||
p.type = TypeInfo(*param.type_name);
|
||||
}
|
||||
p.is_var = param.is_var;
|
||||
p.is_out = param.is_out;
|
||||
sig.parameters.push_back(p);
|
||||
}
|
||||
if (arg.signature.return_type)
|
||||
{
|
||||
sig.return_type = TypeInfo(*arg.signature.return_type);
|
||||
}
|
||||
|
||||
auto key = SymbolCache::MakeKeyFromAST(
|
||||
arg.name, Kind::kFunction, arg.name_location, sig);
|
||||
const SymbolPtr* cached = cache_.Find(key);
|
||||
|
||||
if (cached && *cached)
|
||||
{
|
||||
auto func = std::dynamic_pointer_cast<Function>(*cached);
|
||||
if (func)
|
||||
{
|
||||
return scope->InsertFunction(func);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, ast::ClassDefinition>)
|
||||
{
|
||||
auto key = SymbolCache::MakeKeyFromAST(
|
||||
arg.name, Kind::kClass, arg.name_location);
|
||||
const SymbolPtr* cached = cache_.Find(key);
|
||||
|
||||
if (cached && *cached)
|
||||
{
|
||||
return scope->Insert(*cached);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, ast::UnitDefinition>)
|
||||
{
|
||||
// Unit 支持复用
|
||||
if (registry)
|
||||
{
|
||||
return TryReuseUnit(arg, registry);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 其他类型(Expression, Block 等)直接跳过
|
||||
return true;
|
||||
}
|
||||
},
|
||||
node);
|
||||
}
|
||||
|
||||
bool IncrementalEngine::TryReuseUnit(
|
||||
const ast::UnitDefinition& unit_ast,
|
||||
SymbolRegistry* registry)
|
||||
{
|
||||
if (!registry)
|
||||
return false;
|
||||
|
||||
auto key = SymbolCache::MakeKeyFromAST(
|
||||
unit_ast.name, Kind::kUnit, unit_ast.name_location);
|
||||
const SymbolPtr* cached = cache_.Find(key);
|
||||
|
||||
if (cached && *cached)
|
||||
{
|
||||
auto unit = std::dynamic_pointer_cast<Unit>(*cached);
|
||||
if (unit)
|
||||
{
|
||||
// 尝试将缓存的 Unit 添加到 Registry
|
||||
return registry->AddUnit(unit);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void IncrementalEngine::CacheSymbol(const ast::ASTNode& node, Table* scope)
|
||||
{
|
||||
std::visit([this, scope](auto&& arg) {
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
|
||||
if constexpr (std::is_same_v<T, ast::VarDeclaration> ||
|
||||
std::is_same_v<T, ast::GlobalDeclaration> ||
|
||||
std::is_same_v<T, ast::StaticDeclaration>)
|
||||
{
|
||||
auto result = scope->LookupLocal(arg.name);
|
||||
if (result && result.symbol)
|
||||
{
|
||||
auto key = SymbolCache::MakeKeyFromAST(
|
||||
arg.name, result.symbol->kind, arg.name_location);
|
||||
|
||||
const auto& symbols = scope->Symbols();
|
||||
auto it = symbols.find(arg.name);
|
||||
if (it != symbols.end())
|
||||
{
|
||||
cache_.Insert(key, it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, ast::ConstDeclaration>)
|
||||
{
|
||||
auto result = scope->LookupLocal(arg.name);
|
||||
if (result && result.symbol)
|
||||
{
|
||||
auto key = SymbolCache::MakeKeyFromAST(
|
||||
arg.name, Kind::kConstant, arg.name_location);
|
||||
|
||||
const auto& symbols = scope->Symbols();
|
||||
auto it = symbols.find(arg.name);
|
||||
if (it != symbols.end())
|
||||
{
|
||||
cache_.Insert(key, it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, ast::FunctionDefinition>)
|
||||
{
|
||||
auto result = scope->LookupLocal(arg.name);
|
||||
if (result && result.symbol)
|
||||
{
|
||||
// 创建签名用于缓存键
|
||||
Signature sig;
|
||||
for (const auto& param : arg.signature.parameters)
|
||||
{
|
||||
Signature::Param p;
|
||||
p.name = param.name;
|
||||
if (param.type_name)
|
||||
{
|
||||
p.type = TypeInfo(*param.type_name);
|
||||
}
|
||||
p.is_var = param.is_var;
|
||||
p.is_out = param.is_out;
|
||||
sig.parameters.push_back(p);
|
||||
}
|
||||
if (arg.signature.return_type)
|
||||
{
|
||||
sig.return_type = TypeInfo(*arg.signature.return_type);
|
||||
}
|
||||
|
||||
auto key = SymbolCache::MakeKeyFromAST(
|
||||
arg.name, Kind::kFunction, arg.name_location, sig);
|
||||
|
||||
const auto& symbols = scope->Symbols();
|
||||
auto it = symbols.find(arg.name);
|
||||
if (it != symbols.end())
|
||||
{
|
||||
cache_.Insert(key, it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, ast::ClassDefinition>)
|
||||
{
|
||||
auto result = scope->LookupLocal(arg.name);
|
||||
if (result && result.symbol)
|
||||
{
|
||||
auto key = SymbolCache::MakeKeyFromAST(
|
||||
arg.name, Kind::kClass, arg.name_location);
|
||||
|
||||
const auto& symbols = scope->Symbols();
|
||||
auto it = symbols.find(arg.name);
|
||||
if (it != symbols.end())
|
||||
{
|
||||
cache_.Insert(key, it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, ast::UnitDefinition>)
|
||||
{
|
||||
// Unit 缓存需要从 Registry 获取
|
||||
// 这里暂时不处理,在 BuildCache 中统一处理
|
||||
}
|
||||
// 其他类型不需要缓存
|
||||
},
|
||||
node);
|
||||
}
|
||||
|
||||
void IncrementalEngine::BuildCache(const SymbolRegistry& registry)
|
||||
{
|
||||
// 缓存所有 Unit
|
||||
for (const auto& [name, unit] : registry.Units())
|
||||
{
|
||||
auto key = SymbolCache::MakeKey(unit.get());
|
||||
cache_.Insert(key, unit);
|
||||
|
||||
// 递归缓存 Unit 内部的符号
|
||||
if (unit->interface_symbols)
|
||||
CacheScopeRecursive(unit->interface_symbols.get());
|
||||
if (unit->implementation_symbols)
|
||||
CacheScopeRecursive(unit->implementation_symbols.get());
|
||||
}
|
||||
|
||||
// 缓存全局作用域
|
||||
CacheScopeRecursive(const_cast<Table*>(registry.GlobalScope()));
|
||||
}
|
||||
|
||||
void IncrementalEngine::CacheScopeRecursive(Table* scope)
|
||||
{
|
||||
if (!scope)
|
||||
return;
|
||||
|
||||
// 缓存当前作用域的所有符号
|
||||
for (const auto& [name, symbol] : scope->Symbols())
|
||||
{
|
||||
auto key = SymbolCache::MakeKey(symbol.get());
|
||||
cache_.Insert(key, symbol);
|
||||
|
||||
// 递归缓存类成员
|
||||
if (auto* cls = dynamic_cast<Class*>(symbol.get()))
|
||||
{
|
||||
if (cls->members)
|
||||
{
|
||||
CacheScopeRecursive(cls->members.get());
|
||||
}
|
||||
}
|
||||
|
||||
// 递归缓存函数体作用域
|
||||
if (auto* func = dynamic_cast<Function*>(symbol.get()))
|
||||
{
|
||||
if (func->body_scope)
|
||||
{
|
||||
CacheScopeRecursive(func->body_scope.get());
|
||||
}
|
||||
}
|
||||
|
||||
// 递归缓存构造函数体作用域
|
||||
if (auto* ctor = dynamic_cast<Constructor*>(symbol.get()))
|
||||
{
|
||||
if (ctor->body_scope)
|
||||
{
|
||||
CacheScopeRecursive(ctor->body_scope.get());
|
||||
}
|
||||
}
|
||||
|
||||
// 递归缓存析构函数体作用域
|
||||
if (auto* dtor = dynamic_cast<Destructor*>(symbol.get()))
|
||||
{
|
||||
if (dtor->body_scope)
|
||||
{
|
||||
CacheScopeRecursive(dtor->body_scope.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 管理接口 ====================
|
||||
|
||||
void IncrementalEngine::Clear()
|
||||
{
|
||||
cache_.Clear();
|
||||
}
|
||||
|
||||
void IncrementalEngine::SetMaxCacheSize(size_t max_size)
|
||||
{
|
||||
max_cache_size_ = max_size;
|
||||
cache_.SetMaxSize(max_size);
|
||||
}
|
||||
|
||||
size_t IncrementalEngine::GetCacheSize() const
|
||||
{
|
||||
return cache_.Size();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../ast/types.hpp"
|
||||
#include "../core/registry.hpp"
|
||||
#include "../core/table.hpp"
|
||||
#include "./incremental.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
/**
|
||||
* 增量构建引擎 - 管理符号缓存和复用
|
||||
*
|
||||
* 职责:
|
||||
* - 管理符号缓存 (SymbolCache)
|
||||
* - 提供符号复用接口
|
||||
* - 提供符号缓存接口
|
||||
* - 构建全局缓存
|
||||
*
|
||||
* 不负责:
|
||||
* - 依赖追踪(移到语义分析阶段)
|
||||
* - 类型解析(移到语义分析阶段)
|
||||
*/
|
||||
class IncrementalEngine
|
||||
{
|
||||
public:
|
||||
IncrementalEngine();
|
||||
|
||||
// ==================== 符号复用与缓存 ====================
|
||||
|
||||
/**
|
||||
* 尝试从缓存复用符号
|
||||
* @param node AST 节点
|
||||
* @param scope 当前作用域
|
||||
* @param registry 符号注册表(用于 Unit 复用)
|
||||
* @return 是否成功复用
|
||||
*/
|
||||
bool TryReuseSymbol(const ast::ASTNode& node, Table* scope, SymbolRegistry* registry = nullptr);
|
||||
|
||||
/**
|
||||
* 缓存当前符号
|
||||
* @param node AST 节点
|
||||
* @param scope 当前作用域
|
||||
*/
|
||||
void CacheSymbol(const ast::ASTNode& node, Table* scope);
|
||||
|
||||
/**
|
||||
* 从整个注册表构建缓存
|
||||
* @param registry 符号注册表
|
||||
*/
|
||||
void BuildCache(const SymbolRegistry& registry);
|
||||
|
||||
// ==================== 管理接口 ====================
|
||||
|
||||
void Clear();
|
||||
void SetMaxCacheSize(size_t max_size);
|
||||
size_t GetCacheSize() const;
|
||||
|
||||
// 访问器
|
||||
SymbolCache& GetCache() { return cache_; }
|
||||
const SymbolCache& GetCache() const { return cache_; }
|
||||
|
||||
private:
|
||||
// ==================== 内部辅助方法 ====================
|
||||
|
||||
// 递归缓存作用域中的所有符号
|
||||
void CacheScopeRecursive(Table* scope);
|
||||
|
||||
// 尝试复用 Unit
|
||||
bool TryReuseUnit(const ast::UnitDefinition& unit_ast, SymbolRegistry* registry);
|
||||
|
||||
private:
|
||||
SymbolCache cache_;
|
||||
size_t max_cache_size_;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
#include "./type.hpp"
|
||||
#include <sstream>
|
||||
#include <cctype>
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
// ==================== TypeFactory 实现 ====================
|
||||
|
||||
TypeInfo TypeFactory::FromAnnotation(const std::string& annotation)
|
||||
{
|
||||
// 直接存储原始注解字符串,不做任何解析
|
||||
// 类型引用的解析将在语义分析阶段完成
|
||||
return TypeInfo(Trim(annotation));
|
||||
}
|
||||
|
||||
std::string TypeFactory::Trim(const std::string& str)
|
||||
{
|
||||
size_t start = 0;
|
||||
while (start < str.length() && std::isspace(static_cast<unsigned char>(str[start])))
|
||||
++start;
|
||||
|
||||
if (start == str.length())
|
||||
return "";
|
||||
|
||||
size_t end = str.length();
|
||||
while (end > start && std::isspace(static_cast<unsigned char>(str[end - 1])))
|
||||
--end;
|
||||
|
||||
return str.substr(start, end - start);
|
||||
}
|
||||
|
||||
// ==================== TypeFormatter 实现 ====================
|
||||
|
||||
std::string TypeFormatter::ToString(const TypeInfo& type)
|
||||
{
|
||||
if (!type.HasAnnotation())
|
||||
return "<no annotation>";
|
||||
|
||||
return type.Annotation();
|
||||
}
|
||||
|
||||
std::string TypeFormatter::ToDebugString(const TypeInfo& type)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "TypeInfo { ";
|
||||
|
||||
if (type.HasAnnotation())
|
||||
{
|
||||
oss << "annotation: \"" << type.Annotation() << "\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
oss << "no annotation";
|
||||
}
|
||||
|
||||
oss << " }";
|
||||
return oss.str();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "../core/symbol.hpp"
|
||||
|
||||
namespace lsp::language::symbol
|
||||
{
|
||||
// ==================== 类型工厂 ====================
|
||||
|
||||
/**
|
||||
* 类型工厂 - 仅用于符号表构建
|
||||
*
|
||||
* 职责:
|
||||
* - 从类型注解字符串创建 TypeInfo
|
||||
* - 存储原始字符串,不解析任何引用
|
||||
*
|
||||
* 不负责:
|
||||
* - 类型引用解析(属于语义分析)
|
||||
* - 表达式解析(属于语义分析)
|
||||
* - 类型检查(属于语义分析)
|
||||
*/
|
||||
class TypeFactory
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* 从类型注解创建 TypeInfo
|
||||
* @param annotation 类型注解字符串(如 "Integer", "TMyClass")
|
||||
* @return TypeInfo 对象
|
||||
*
|
||||
* 注意:直接存储原始字符串,不做任何解析
|
||||
*/
|
||||
static TypeInfo FromAnnotation(const std::string& annotation);
|
||||
|
||||
private:
|
||||
// 辅助函数:去除首尾空格
|
||||
static std::string Trim(const std::string& str);
|
||||
};
|
||||
|
||||
// ==================== 类型格式化器 ====================
|
||||
|
||||
/**
|
||||
* 类型格式化器 - 用于调试和日志输出
|
||||
*/
|
||||
class TypeFormatter
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* 转换为可读字符串
|
||||
*/
|
||||
static std::string ToString(const TypeInfo& type);
|
||||
|
||||
/**
|
||||
* 转换为调试字符串(包含详细信息)
|
||||
*/
|
||||
static std::string ToDebugString(const TypeInfo& type);
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user