[Feat] 详细区分左值(LvObject)与右值(RvObject -> ObjectPtr)

[Impl] 重构evaluator.cpp + hpp 全部
[Feat] 增加对于IndexExpr的解析
[Fix][Impl] 现在点运算符不由BinaryExpr负责,增加MemberExpr,单独实现解析
[Impl] 项目目录全部翻修, src/目录下单独文件夹放置每一个模块
This commit is contained in:
2025-12-24 17:51:49 +08:00
parent 3227230aa2
commit fc35368d85
70 changed files with 1558 additions and 1233 deletions

267
src/Context/context.hpp Normal file
View File

@@ -0,0 +1,267 @@
#pragma once
#include <unordered_map>
#include <iostream>
#include <memory>
#include <Context/context_forward.hpp>
#include <Core/fig_string.hpp>
#include <Value/value.hpp>
namespace Fig
{
class Context : public std::enable_shared_from_this<Context>
{
private:
FString scopeName;
std::unordered_map<FString, std::shared_ptr<VariableSlot>> variables;
std::unordered_map<std::size_t, Function> functions;
std::unordered_map<std::size_t, FString> functionNames;
std::unordered_map<std::size_t, FString> structTypeNames;
public:
ContextPtr parent;
Context(const Context &) = default;
Context(const FString &name, ContextPtr p = nullptr) :
scopeName(name), parent(p) {}
Context(const FString &name, std::unordered_map<FString, TypeInfo> types, std::unordered_map<FString, std::shared_ptr<VariableSlot>> vars, std::unordered_map<FString, AccessModifier> _ams) :
scopeName(std::move(name)), variables(std::move(vars)) {}
void setParent(ContextPtr _parent)
{
parent = _parent;
}
void setScopeName(FString _name)
{
scopeName = std::move(_name);
}
FString getScopeName() const
{
return scopeName;
}
void merge(const Context &c)
{
variables.insert(c.variables.begin(), c.variables.end());
functions.insert(c.functions.begin(), c.functions.end());
functionNames.insert(c.functionNames.begin(), c.functionNames.end());
structTypeNames.insert(c.structTypeNames.begin(), c.structTypeNames.end());
}
std::unordered_map<size_t, Function> getFunctions() const
{
return functions;
}
std::shared_ptr<VariableSlot> get(const FString &name)
{
auto it = variables.find(name);
if (it != variables.end())
return it->second;
if (parent)
return parent->get(name);
throw RuntimeError(FStringView(std::format("Variable '{}' not defined", name.toBasicString())));
}
AccessModifier getAccessModifier(const FString &name)
{
if (variables.contains(name))
{
return variables[name]->am;
}
else if (parent != nullptr)
{
return parent->getAccessModifier(name);
}
else
{
throw RuntimeError(FStringView(std::format("Variable '{}' not defined", name.toBasicString())));
}
}
bool isVariableMutable(const FString &name)
{
AccessModifier am = getAccessModifier(name); // may throw
return !isAccessConst(am);
}
bool isVariablePublic(const FString &name)
{
AccessModifier am = getAccessModifier(name); // may throw
return isAccessPublic(am);
}
void set(const FString &name, ObjectPtr value)
{
if (variables.contains(name))
{
if (!isVariableMutable(name))
{
throw RuntimeError(FStringView(std::format("Variable '{}' is immutable", name.toBasicString())));
}
variables[name]->value = value;
}
else if (parent != nullptr)
{
parent->set(name, value);
}
else
{
throw RuntimeError(FStringView(std::format("Variable '{}' not defined", name.toBasicString())));
}
}
void _update(const FString &name, ObjectPtr value)
{
if (variables.contains(name))
{
variables[name]->value = value;
}
else if (parent != nullptr)
{
parent->set(name, value);
}
else
{
throw RuntimeError(FStringView(std::format("Variable '{}' not defined", name.toBasicString())));
}
}
void def(const FString &name, const TypeInfo &ti, AccessModifier am, const ObjectPtr &value = Object::getNullInstance())
{
if (containsInThisScope(name))
{
throw RuntimeError(FStringView(std::format("Variable '{}' already defined in this scope", name.toBasicString())));
}
variables[name] = std::make_shared<VariableSlot>(
name,
value,
ti,
am);
if (ti == ValueType::Function and value->getTypeInfo() == ValueType::Function)
{
auto &fn = value->as<Function>();
functions[fn.id] = fn;
functionNames[fn.id] = name;
}
if (ti == ValueType::StructType)
{
auto &st = value->as<StructType>();
structTypeNames[st.id] = name;
}
}
std::optional<Function> getFunction(std::size_t id)
{
auto it = functions.find(id);
if (it != functions.end())
{
return it->second;
}
else if (parent)
{
return parent->getFunction(id);
}
else
{
return std::nullopt;
}
}
std::optional<FString> getFunctionName(std::size_t id)
{
auto it = functionNames.find(id);
if (it != functionNames.end())
{
return it->second;
}
else if (parent)
{
return parent->getFunctionName(id);
}
else
{
return std::nullopt;
}
}
std::optional<FString> getStructName(std::size_t id)
{
auto it = structTypeNames.find(id);
if (it != structTypeNames.end())
{
return it->second;
}
else if (parent)
{
return parent->getFunctionName(id);
}
else
{
return std::nullopt;
}
}
bool contains(const FString &name)
{
if (variables.contains(name))
{
return true;
}
else if (parent != nullptr)
{
return parent->contains(name);
}
return false;
}
bool containsInThisScope(const FString &name) const
{
return variables.contains(name);
}
TypeInfo getTypeInfo(const FString &name)
{
return get(name)->declaredType;
}
bool isInFunctionContext()
{
ContextPtr ctx = shared_from_this();
while (ctx)
{
if (ctx->getScopeName().find(u8"<Function ") == 0)
{
return true;
}
ctx = ctx->parent;
}
return false;
}
bool isInLoopContext()
{
ContextPtr ctx = shared_from_this();
while (ctx)
{
if (ctx->getScopeName().find(u8"<While ") == 0 or ctx->getScopeName().find(u8"<For ") == 0)
{
return true;
}
ctx = ctx->parent;
}
return false;
}
void printStackTrace(std::ostream &os = std::cerr, int indent = 0) const
{
const Context *ctx = this;
std::vector<const Context *> chain;
while (ctx)
{
chain.push_back(ctx);
ctx = ctx->parent.get();
}
os << "[STACK TRACE]\n";
for (int i = static_cast<int>(chain.size()) - 1; i >= 0; --i)
{
os << " #" << (chain.size() - 1 - i)
<< " " << chain[i]->scopeName.toBasicString()
<< "\n";
}
}
};
}; // namespace Fig