[Fix] 修复Implement没有向上级查找的BUG ! 非常抱歉
This commit is contained in:
@@ -33,37 +33,33 @@ namespace Fig
|
||||
std::unordered_map<std::size_t, FString> functionNames;
|
||||
|
||||
// implRegistry <Struct, ordered list of ImplRecord>
|
||||
std::unordered_map<TypeInfo, std::vector<ImplRecord>, TypeInfoHash> implRegistry;
|
||||
std::unordered_map<TypeInfo, std::vector<ImplRecord>, TypeInfoHash>
|
||||
implRegistry;
|
||||
|
||||
public:
|
||||
ContextPtr parent;
|
||||
|
||||
Context(const Context &) = default;
|
||||
Context(const FString &name, ContextPtr p = nullptr) :
|
||||
scopeName(name), parent(p) {}
|
||||
|
||||
void setParent(ContextPtr _parent)
|
||||
scopeName(name), parent(p)
|
||||
{
|
||||
parent = _parent;
|
||||
}
|
||||
|
||||
void setScopeName(FString _name)
|
||||
{
|
||||
scopeName = std::move(_name);
|
||||
}
|
||||
void setParent(ContextPtr _parent) { parent = _parent; }
|
||||
|
||||
FString getScopeName() const
|
||||
{
|
||||
return scopeName;
|
||||
}
|
||||
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());
|
||||
functionNames.insert(c.functionNames.begin(),
|
||||
c.functionNames.end());
|
||||
implRegistry.insert(c.implRegistry.begin(), c.implRegistry.end());
|
||||
// structTypeNames.insert(c.structTypeNames.begin(), c.structTypeNames.end());
|
||||
// structTypeNames.insert(c.structTypeNames.begin(),
|
||||
// c.structTypeNames.end());
|
||||
}
|
||||
|
||||
std::unordered_map<size_t, Function> getFunctions() const
|
||||
@@ -74,25 +70,22 @@ namespace Fig
|
||||
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(FString(std::format("Variable '{}' not defined", name.toBasicString())));
|
||||
if (it != variables.end()) return it->second;
|
||||
if (parent) return parent->get(name);
|
||||
throw RuntimeError(FString(std::format("Variable '{}' not defined",
|
||||
name.toBasicString())));
|
||||
}
|
||||
AccessModifier getAccessModifier(const FString &name)
|
||||
{
|
||||
if (variables.contains(name))
|
||||
{
|
||||
return variables[name]->am;
|
||||
}
|
||||
if (variables.contains(name)) { return variables[name]->am; }
|
||||
else if (parent != nullptr)
|
||||
{
|
||||
return parent->getAccessModifier(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw RuntimeError(FString(std::format("Variable '{}' not defined", name.toBasicString())));
|
||||
throw RuntimeError(FString(std::format(
|
||||
"Variable '{}' not defined", name.toBasicString())));
|
||||
}
|
||||
}
|
||||
bool isVariableMutable(const FString &name)
|
||||
@@ -111,46 +104,43 @@ namespace Fig
|
||||
{
|
||||
if (!isVariableMutable(name))
|
||||
{
|
||||
throw RuntimeError(FString(std::format("Variable '{}' is immutable", name.toBasicString())));
|
||||
throw RuntimeError(FString(std::format(
|
||||
"Variable '{}' is immutable", name.toBasicString())));
|
||||
}
|
||||
variables[name]->value = value;
|
||||
}
|
||||
else if (parent != nullptr)
|
||||
{
|
||||
parent->set(name, value);
|
||||
}
|
||||
else if (parent != nullptr) { parent->set(name, value); }
|
||||
else
|
||||
{
|
||||
throw RuntimeError(FString(std::format("Variable '{}' not defined", name.toBasicString())));
|
||||
throw RuntimeError(FString(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->_update(name, value);
|
||||
}
|
||||
if (variables.contains(name)) { variables[name]->value = value; }
|
||||
else if (parent != nullptr) { parent->_update(name, value); }
|
||||
else
|
||||
{
|
||||
throw RuntimeError(FString(std::format("Variable '{}' not defined", name.toBasicString())));
|
||||
throw RuntimeError(FString(std::format(
|
||||
"Variable '{}' not defined", name.toBasicString())));
|
||||
}
|
||||
}
|
||||
void def(const FString &name, const TypeInfo &ti, AccessModifier am, const ObjectPtr &value = Object::getNullInstance())
|
||||
void def(const FString &name,
|
||||
const TypeInfo &ti,
|
||||
AccessModifier am,
|
||||
const ObjectPtr &value = Object::getNullInstance())
|
||||
{
|
||||
if (containsInThisScope(name))
|
||||
{
|
||||
throw RuntimeError(FString(std::format("Variable '{}' already defined in this scope", name.toBasicString())));
|
||||
throw RuntimeError(FString(
|
||||
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)
|
||||
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;
|
||||
@@ -165,34 +155,16 @@ namespace Fig
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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)
|
||||
// {
|
||||
@@ -212,14 +184,8 @@ namespace Fig
|
||||
// }
|
||||
bool contains(const FString &name)
|
||||
{
|
||||
if (variables.contains(name))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (parent != nullptr)
|
||||
{
|
||||
return parent->contains(name);
|
||||
}
|
||||
if (variables.contains(name)) { return true; }
|
||||
else if (parent != nullptr) { return parent->contains(name); }
|
||||
return false;
|
||||
}
|
||||
bool containsInThisScope(const FString &name) const
|
||||
@@ -249,7 +215,8 @@ namespace Fig
|
||||
ContextPtr ctx = shared_from_this();
|
||||
while (ctx)
|
||||
{
|
||||
if (ctx->getScopeName().find(u8"<While ") == 0 or ctx->getScopeName().find(u8"<For ") == 0)
|
||||
if (ctx->getScopeName().find(u8"<While ") == 0
|
||||
or ctx->getScopeName().find(u8"<For ") == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -258,71 +225,73 @@ namespace Fig
|
||||
return false;
|
||||
}
|
||||
|
||||
bool hasImplRegisted(const TypeInfo &structType, const TypeInfo &interfaceType) const
|
||||
bool hasImplRegisted(const TypeInfo &structType,
|
||||
const TypeInfo &interfaceType) const
|
||||
{
|
||||
auto it = implRegistry.find(structType);
|
||||
if (it != implRegistry.end())
|
||||
{
|
||||
for (auto &r : it->second)
|
||||
{
|
||||
if (r.interfaceType == interfaceType)
|
||||
return true;
|
||||
if (r.interfaceType == interfaceType) return true;
|
||||
}
|
||||
}
|
||||
return parent && parent->hasImplRegisted(structType, interfaceType);
|
||||
}
|
||||
|
||||
std::optional<ImplRecord> getImplRecord(const TypeInfo &structType, const TypeInfo &interfaceType) const
|
||||
std::optional<ImplRecord>
|
||||
getImplRecord(const TypeInfo &structType,
|
||||
const TypeInfo &interfaceType) const
|
||||
{
|
||||
auto it = implRegistry.find(structType);
|
||||
if (it != implRegistry.end())
|
||||
{
|
||||
for (auto &r : it->second)
|
||||
{
|
||||
if (r.interfaceType == interfaceType)
|
||||
return r;
|
||||
if (r.interfaceType == interfaceType) return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (parent)
|
||||
return parent->getImplRecord(structType, interfaceType);
|
||||
if (parent) return parent->getImplRecord(structType, interfaceType);
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void setImplRecord(const TypeInfo &structType, const TypeInfo &interfaceType, const ImplRecord &record)
|
||||
void setImplRecord(const TypeInfo &structType,
|
||||
const TypeInfo &interfaceType,
|
||||
const ImplRecord &record)
|
||||
{
|
||||
auto &list = implRegistry[structType];
|
||||
|
||||
for (auto &r : list)
|
||||
{
|
||||
if (r.interfaceType == interfaceType)
|
||||
return;
|
||||
if (r.interfaceType == interfaceType) return;
|
||||
}
|
||||
|
||||
list.push_back(record); // order is the level
|
||||
}
|
||||
|
||||
bool hasMethodImplemented(const TypeInfo &structType, const FString &functionName) const
|
||||
bool hasMethodImplemented(const TypeInfo &structType,
|
||||
const FString &functionName) const
|
||||
{
|
||||
auto it = implRegistry.find(structType);
|
||||
if (it == implRegistry.end())
|
||||
return false;
|
||||
|
||||
for (auto &record : it->second)
|
||||
if (it != implRegistry.end())
|
||||
{
|
||||
if (record.implMethods.contains(functionName))
|
||||
return true;
|
||||
for (auto &record : it->second)
|
||||
{
|
||||
if (record.implMethods.contains(functionName)) return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return parent
|
||||
&& parent->hasMethodImplemented(structType, functionName);
|
||||
}
|
||||
|
||||
bool hasDefaultImplementedMethod(const TypeInfo &structType, const FString &functionName) const
|
||||
bool hasDefaultImplementedMethod(const TypeInfo &structType,
|
||||
const FString &functionName) const
|
||||
{
|
||||
auto it = implRegistry.find(structType);
|
||||
if (it == implRegistry.end())
|
||||
return false;
|
||||
if (it == implRegistry.end()) return false;
|
||||
|
||||
std::vector<TypeInfo> implementedInterfaces;
|
||||
for (auto &record : it->second)
|
||||
@@ -330,19 +299,16 @@ namespace Fig
|
||||
|
||||
for (auto &[_, slot] : variables)
|
||||
{
|
||||
if (!slot->value->is<InterfaceType>())
|
||||
continue;
|
||||
if (!slot->value->is<InterfaceType>()) continue;
|
||||
|
||||
InterfaceType &interface = slot->value->as<InterfaceType>();
|
||||
|
||||
bool implemented =
|
||||
std::any_of(
|
||||
implementedInterfaces.begin(),
|
||||
implementedInterfaces.end(),
|
||||
[&](const TypeInfo &ti) { return ti == interface.type; });
|
||||
bool implemented = std::any_of(
|
||||
implementedInterfaces.begin(),
|
||||
implementedInterfaces.end(),
|
||||
[&](const TypeInfo &ti) { return ti == interface.type; });
|
||||
|
||||
if (!implemented)
|
||||
continue;
|
||||
if (!implemented) continue;
|
||||
|
||||
for (auto &method : interface.methods)
|
||||
{
|
||||
@@ -354,7 +320,8 @@ namespace Fig
|
||||
return false;
|
||||
}
|
||||
|
||||
Function getDefaultImplementedMethod(const TypeInfo &structType, const FString &functionName)
|
||||
Function getDefaultImplementedMethod(const TypeInfo &structType,
|
||||
const FString &functionName)
|
||||
{
|
||||
// O(N²)
|
||||
// SLOW
|
||||
@@ -365,8 +332,7 @@ namespace Fig
|
||||
// i dont give a fuck
|
||||
|
||||
auto it = implRegistry.find(structType);
|
||||
if (it == implRegistry.end())
|
||||
assert(false);
|
||||
if (it == implRegistry.end()) assert(false);
|
||||
|
||||
std::vector<TypeInfo> implementedInterfaces;
|
||||
for (auto &record : it->second)
|
||||
@@ -374,32 +340,27 @@ namespace Fig
|
||||
|
||||
for (auto &[_, slot] : variables)
|
||||
{
|
||||
if (!slot->value->is<InterfaceType>())
|
||||
continue;
|
||||
if (!slot->value->is<InterfaceType>()) continue;
|
||||
|
||||
InterfaceType &interface = slot->value->as<InterfaceType>();
|
||||
|
||||
bool implemented =
|
||||
std::any_of(
|
||||
implementedInterfaces.begin(),
|
||||
implementedInterfaces.end(),
|
||||
[&](const TypeInfo &ti) { return ti == interface.type; });
|
||||
bool implemented = std::any_of(
|
||||
implementedInterfaces.begin(),
|
||||
implementedInterfaces.end(),
|
||||
[&](const TypeInfo &ti) { return ti == interface.type; });
|
||||
|
||||
if (!implemented)
|
||||
continue;
|
||||
if (!implemented) continue;
|
||||
|
||||
for (auto &method : interface.methods)
|
||||
{
|
||||
if (method.name == functionName)
|
||||
{
|
||||
if (!method.hasDefaultBody())
|
||||
assert(false);
|
||||
if (!method.hasDefaultBody()) assert(false);
|
||||
|
||||
return Function(
|
||||
method.paras,
|
||||
TypeInfo(method.returnType),
|
||||
method.defaultBody,
|
||||
shared_from_this());
|
||||
return Function(method.paras,
|
||||
TypeInfo(method.returnType),
|
||||
method.defaultBody,
|
||||
shared_from_this());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -407,17 +368,23 @@ namespace Fig
|
||||
assert(false);
|
||||
}
|
||||
|
||||
const Function &getImplementedMethod(const TypeInfo &structType, const FString &functionName) const
|
||||
const Function &getImplementedMethod(const TypeInfo &structType,
|
||||
const FString &functionName) const
|
||||
{
|
||||
const auto &list = implRegistry.at(structType);
|
||||
for (auto &record : list)
|
||||
auto it = implRegistry.find(structType);
|
||||
if (it != implRegistry.end())
|
||||
{
|
||||
auto it = record.implMethods.find(functionName);
|
||||
if (it != record.implMethods.end())
|
||||
return it->second;
|
||||
for (auto &record : it->second)
|
||||
{
|
||||
auto fit = record.implMethods.find(functionName);
|
||||
if (fit != record.implMethods.end()) return fit->second;
|
||||
}
|
||||
}
|
||||
|
||||
assert(false);
|
||||
if (parent)
|
||||
return parent->getImplementedMethod(structType, functionName);
|
||||
|
||||
assert(false); // not found
|
||||
}
|
||||
|
||||
void printStackTrace(std::ostream &os = std::cerr, int indent = 0) const
|
||||
@@ -434,9 +401,8 @@ namespace Fig
|
||||
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";
|
||||
os << " #" << (chain.size() - 1 - i) << " "
|
||||
<< chain[i]->scopeName.toBasicString() << "\n";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user