forked from PuqiAR/Fig-TreeWalker
[Impl] StructInstance现在记录parent TypeInfo, StructType改用TypeInfo
This commit is contained in:
@@ -20,7 +20,7 @@ namespace Fig
|
|||||||
|
|
||||||
std::unordered_map<std::size_t, Function> functions;
|
std::unordered_map<std::size_t, Function> functions;
|
||||||
std::unordered_map<std::size_t, FString> functionNames;
|
std::unordered_map<std::size_t, FString> functionNames;
|
||||||
std::unordered_map<std::size_t, FString> structTypeNames;
|
// std::unordered_map<std::size_t, FString> structTypeNames;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ContextPtr parent;
|
ContextPtr parent;
|
||||||
@@ -49,7 +49,7 @@ namespace Fig
|
|||||||
variables.insert(c.variables.begin(), c.variables.end());
|
variables.insert(c.variables.begin(), c.variables.end());
|
||||||
functions.insert(c.functions.begin(), c.functions.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());
|
||||||
structTypeNames.insert(c.structTypeNames.begin(), c.structTypeNames.end());
|
// structTypeNames.insert(c.structTypeNames.begin(), c.structTypeNames.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<size_t, Function> getFunctions() const
|
std::unordered_map<size_t, Function> getFunctions() const
|
||||||
@@ -142,11 +142,11 @@ namespace Fig
|
|||||||
functions[fn.id] = fn;
|
functions[fn.id] = fn;
|
||||||
functionNames[fn.id] = name;
|
functionNames[fn.id] = name;
|
||||||
}
|
}
|
||||||
if (ti == ValueType::StructType)
|
// if (ti == ValueType::StructType)
|
||||||
{
|
// {
|
||||||
auto &st = value->as<StructType>();
|
// auto &st = value->as<StructType>();
|
||||||
structTypeNames[st.id] = name;
|
// structTypeNames[st.id] = name;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
std::optional<Function> getFunction(std::size_t id)
|
std::optional<Function> getFunction(std::size_t id)
|
||||||
{
|
{
|
||||||
@@ -180,22 +180,22 @@ namespace Fig
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::optional<FString> getStructName(std::size_t id)
|
// std::optional<FString> getStructName(std::size_t id)
|
||||||
{
|
// {
|
||||||
auto it = structTypeNames.find(id);
|
// auto it = structTypeNames.find(id);
|
||||||
if (it != structTypeNames.end())
|
// if (it != structTypeNames.end())
|
||||||
{
|
// {
|
||||||
return it->second;
|
// return it->second;
|
||||||
}
|
// }
|
||||||
else if (parent)
|
// else if (parent)
|
||||||
{
|
// {
|
||||||
return parent->getStructName(id);
|
// return parent->getStructName(id);
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
return std::nullopt;
|
// return std::nullopt;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
bool contains(const FString &name)
|
bool contains(const FString &name)
|
||||||
{
|
{
|
||||||
if (variables.contains(name))
|
if (variables.contains(name))
|
||||||
|
|||||||
@@ -11,6 +11,20 @@
|
|||||||
|
|
||||||
namespace Fig
|
namespace Fig
|
||||||
{
|
{
|
||||||
|
bool Evaluator::isTypeMatch(const TypeInfo &expected, ObjectPtr obj)
|
||||||
|
{
|
||||||
|
if (expected == ValueType::Any)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
TypeInfo actual = obj->getTypeInfo();
|
||||||
|
|
||||||
|
if (actual != ValueType::StructInstance)
|
||||||
|
return expected == actual;
|
||||||
|
|
||||||
|
const StructInstance &si = obj->as<StructInstance>();
|
||||||
|
return si.parentType == expected;
|
||||||
|
}
|
||||||
|
|
||||||
LvObject Evaluator::evalVarExpr(Ast::VarExpr var, ContextPtr ctx)
|
LvObject Evaluator::evalVarExpr(Ast::VarExpr var, ContextPtr ctx)
|
||||||
{
|
{
|
||||||
const FString &name = var->name;
|
const FString &name = var->name;
|
||||||
@@ -300,8 +314,7 @@ namespace Fig
|
|||||||
LvObject lv = evalLv(lexp, ctx);
|
LvObject lv = evalLv(lexp, ctx);
|
||||||
ObjectPtr rhs = eval(rexp, ctx);
|
ObjectPtr rhs = eval(rexp, ctx);
|
||||||
lv.set(std::make_shared<Object>(
|
lv.set(std::make_shared<Object>(
|
||||||
*(lv.get()) + *rhs
|
*(lv.get()) + *rhs));
|
||||||
));
|
|
||||||
return rhs;
|
return rhs;
|
||||||
}
|
}
|
||||||
case Operator::MinusAssign: {
|
case Operator::MinusAssign: {
|
||||||
@@ -437,7 +450,7 @@ namespace Fig
|
|||||||
TypeInfo expectedType(fnParas.posParas[i].second); // look up type info, if exists a type with the name, use it, else throw
|
TypeInfo expectedType(fnParas.posParas[i].second); // look up type info, if exists a type with the name, use it, else throw
|
||||||
ObjectPtr argVal = eval(fnArgs.argv[i], ctx);
|
ObjectPtr argVal = eval(fnArgs.argv[i], ctx);
|
||||||
TypeInfo actualType = argVal->getTypeInfo();
|
TypeInfo actualType = argVal->getTypeInfo();
|
||||||
if (expectedType != actualType and expectedType != ValueType::Any)
|
if (!isTypeMatch(expectedType, argVal))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"ArgumentTypeMismatchError",
|
u8"ArgumentTypeMismatchError",
|
||||||
@@ -457,7 +470,7 @@ namespace Fig
|
|||||||
TypeInfo expectedType = fnParas.defParas[defParamIndex].second.first;
|
TypeInfo expectedType = fnParas.defParas[defParamIndex].second.first;
|
||||||
|
|
||||||
ObjectPtr defaultVal = eval(fnParas.defParas[defParamIndex].second.second, ctx);
|
ObjectPtr defaultVal = eval(fnParas.defParas[defParamIndex].second.second, ctx);
|
||||||
if (expectedType != defaultVal->getTypeInfo() and expectedType != ValueType::Any)
|
if (!isTypeMatch(expectedType, defaultVal))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"DefaultParameterTypeError",
|
u8"DefaultParameterTypeError",
|
||||||
@@ -471,7 +484,7 @@ namespace Fig
|
|||||||
|
|
||||||
ObjectPtr argVal = eval(fnArgs.argv[i], ctx);
|
ObjectPtr argVal = eval(fnArgs.argv[i], ctx);
|
||||||
TypeInfo actualType = argVal->getTypeInfo();
|
TypeInfo actualType = argVal->getTypeInfo();
|
||||||
if (expectedType != actualType and expectedType != ValueType::Any)
|
if (!isTypeMatch(expectedType, argVal))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"ArgumentTypeMismatchError",
|
u8"ArgumentTypeMismatchError",
|
||||||
@@ -540,7 +553,7 @@ namespace Fig
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fnStruct.retType != retVal->getTypeInfo() and fnStruct.retType != ValueType::Any)
|
if (!isTypeMatch(fnStruct.retType, retVal))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"ReturnTypeMismatchError",
|
u8"ReturnTypeMismatchError",
|
||||||
@@ -728,7 +741,7 @@ namespace Fig
|
|||||||
ObjectPtr defaultVal = eval(field.defaultValue, ctx); // it can't be null here
|
ObjectPtr defaultVal = eval(field.defaultValue, ctx); // it can't be null here
|
||||||
|
|
||||||
// type check
|
// type check
|
||||||
if (expectedType != defaultVal->getTypeInfo() && expectedType != ValueType::Any)
|
if (!isTypeMatch(expectedType, defaultVal))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"StructFieldTypeMismatchError",
|
u8"StructFieldTypeMismatchError",
|
||||||
@@ -746,7 +759,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ObjectPtr &argVal = evaluatedArgs[i].second;
|
const ObjectPtr &argVal = evaluatedArgs[i].second;
|
||||||
if (expectedType != argVal->getTypeInfo() && expectedType != ValueType::Any)
|
if (!isTypeMatch(expectedType, argVal))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"StructFieldTypeMismatchError",
|
u8"StructFieldTypeMismatchError",
|
||||||
@@ -784,7 +797,7 @@ namespace Fig
|
|||||||
|
|
||||||
// type check
|
// type check
|
||||||
const TypeInfo &expectedType = field.type;
|
const TypeInfo &expectedType = field.type;
|
||||||
if (expectedType != defaultVal->getTypeInfo() && expectedType != ValueType::Any)
|
if (!isTypeMatch(expectedType, defaultVal))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"StructFieldTypeMismatchError",
|
u8"StructFieldTypeMismatchError",
|
||||||
@@ -801,7 +814,7 @@ namespace Fig
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const ObjectPtr &argVal = evaluatedArgs[i].second;
|
const ObjectPtr &argVal = evaluatedArgs[i].second;
|
||||||
if (field.type != argVal->getTypeInfo() && field.type != ValueType::Any)
|
if (!isTypeMatch(field.type, argVal))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"StructFieldTypeMismatchError",
|
u8"StructFieldTypeMismatchError",
|
||||||
@@ -824,7 +837,7 @@ namespace Fig
|
|||||||
Function(fn.paras, fn.retType, fn.body, instanceCtx) // change its closureContext to struct instance's context
|
Function(fn.paras, fn.retType, fn.body, instanceCtx) // change its closureContext to struct instance's context
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
return std::make_shared<Object>(StructInstance(structT.id, instanceCtx));
|
return std::make_shared<Object>(StructInstance(structT.type, instanceCtx));
|
||||||
}
|
}
|
||||||
|
|
||||||
case AstType::ListExpr: {
|
case AstType::ListExpr: {
|
||||||
@@ -905,7 +918,7 @@ namespace Fig
|
|||||||
else if (!declaredTypeName.empty())
|
else if (!declaredTypeName.empty())
|
||||||
{
|
{
|
||||||
declaredType = TypeInfo(declaredTypeName);
|
declaredType = TypeInfo(declaredTypeName);
|
||||||
if (value != nullptr && value->getTypeInfo() != declaredType && declaredType != ValueType::Any)
|
if (value != nullptr && !isTypeMatch(declaredType, value))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"TypeError",
|
u8"TypeError",
|
||||||
@@ -1006,12 +1019,13 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
|
|
||||||
AccessModifier am = (stDef->isPublic ? AccessModifier::PublicConst : AccessModifier::Const);
|
AccessModifier am = (stDef->isPublic ? AccessModifier::PublicConst : AccessModifier::Const);
|
||||||
TypeInfo _(stDef->name, true); // register type name
|
TypeInfo type(stDef->name, true); // register type name
|
||||||
ctx->def(
|
ctx->def(
|
||||||
stDef->name,
|
stDef->name,
|
||||||
ValueType::StructType,
|
ValueType::StructType,
|
||||||
am,
|
am,
|
||||||
std::make_shared<Object>(StructType(
|
std::make_shared<Object>(StructType(
|
||||||
|
type,
|
||||||
defContext,
|
defContext,
|
||||||
fields)));
|
fields)));
|
||||||
return StatementResult::normal();
|
return StatementResult::normal();
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
#include <Value/LvObject.hpp>
|
#include <Value/LvObject.hpp>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
|
|
||||||
namespace Fig
|
namespace Fig
|
||||||
{
|
{
|
||||||
struct StatementResult
|
struct StatementResult
|
||||||
@@ -52,6 +51,7 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
ContextPtr global;
|
ContextPtr global;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FString sourcePath;
|
FString sourcePath;
|
||||||
|
|
||||||
@@ -84,8 +84,7 @@ namespace Fig
|
|||||||
name,
|
name,
|
||||||
ValueType::Function,
|
ValueType::Function,
|
||||||
AccessModifier::Const,
|
AccessModifier::Const,
|
||||||
std::make_shared<Object>(f)
|
std::make_shared<Object>(f));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,6 +101,9 @@ namespace Fig
|
|||||||
val);
|
val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isTypeMatch(const TypeInfo &, ObjectPtr);
|
||||||
|
|
||||||
/* Left-value eval*/
|
/* Left-value eval*/
|
||||||
LvObject evalVarExpr(Ast::VarExpr, ContextPtr);
|
LvObject evalVarExpr(Ast::VarExpr, ContextPtr);
|
||||||
LvObject evalMemberExpr(Ast::MemberExpr, ContextPtr); // a.b
|
LvObject evalMemberExpr(Ast::MemberExpr, ContextPtr); // a.b
|
||||||
|
|||||||
@@ -75,7 +75,8 @@ namespace Fig
|
|||||||
{FString(u8"else"), TokenType::Else},
|
{FString(u8"else"), TokenType::Else},
|
||||||
{FString(u8"struct"), TokenType::Struct},
|
{FString(u8"struct"), TokenType::Struct},
|
||||||
{FString(u8"interface"), TokenType::Interface},
|
{FString(u8"interface"), TokenType::Interface},
|
||||||
{FString(u8"implement"), TokenType::Implement},
|
{FString(u8"impl"), TokenType::Implement},
|
||||||
|
{FString(u8"is"), TokenType::Is},
|
||||||
{FString(u8"public"), TokenType::Public},
|
{FString(u8"public"), TokenType::Public},
|
||||||
{FString(u8"return"), TokenType::Return},
|
{FString(u8"return"), TokenType::Return},
|
||||||
{FString(u8"break"), TokenType::Break},
|
{FString(u8"break"), TokenType::Break},
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ namespace Fig
|
|||||||
Else, // else
|
Else, // else
|
||||||
Struct, // struct
|
Struct, // struct
|
||||||
Interface, // interface
|
Interface, // interface
|
||||||
Implement, // implement
|
Implement, // impl
|
||||||
|
Is, // is
|
||||||
Public, // public
|
Public, // public
|
||||||
Return, // return
|
Return, // return
|
||||||
Break, // break
|
Break, // break
|
||||||
|
|||||||
@@ -77,3 +77,16 @@ namespace Fig
|
|||||||
using StringClass = FString;
|
using StringClass = FString;
|
||||||
}; // namespace ValueType
|
}; // namespace ValueType
|
||||||
}; // namespace Fig
|
}; // namespace Fig
|
||||||
|
|
||||||
|
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
template <>
|
||||||
|
struct hash<Fig::TypeInfo>
|
||||||
|
{
|
||||||
|
size_t operator()(const Fig::TypeInfo &t)
|
||||||
|
{
|
||||||
|
return std::hash<size_t>{}(t.getInstanceID());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -1,17 +1,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Context/context_forward.hpp>
|
#include <Context/context_forward.hpp>
|
||||||
|
#include <Value/Type.hpp>
|
||||||
|
|
||||||
namespace Fig
|
namespace Fig
|
||||||
{
|
{
|
||||||
struct StructInstance
|
struct StructInstance
|
||||||
{
|
{
|
||||||
size_t parentId;
|
TypeInfo parentType;
|
||||||
ContextPtr localContext;
|
ContextPtr localContext;
|
||||||
|
|
||||||
// ===== Constructors =====
|
// ===== Constructors =====
|
||||||
StructInstance(size_t _parentId, ContextPtr _localContext) :
|
StructInstance(TypeInfo _parentType, ContextPtr _localContext) :
|
||||||
parentId(_parentId), localContext(std::move(_localContext)) {}
|
parentType(_parentType), localContext(std::move(_localContext)) {}
|
||||||
|
|
||||||
StructInstance(const StructInstance &other) = default;
|
StructInstance(const StructInstance &other) = default;
|
||||||
StructInstance(StructInstance &&) noexcept = default;
|
StructInstance(StructInstance &&) noexcept = default;
|
||||||
@@ -21,7 +22,7 @@ namespace Fig
|
|||||||
// ===== Comparison =====
|
// ===== Comparison =====
|
||||||
bool operator==(const StructInstance &other) const noexcept
|
bool operator==(const StructInstance &other) const noexcept
|
||||||
{
|
{
|
||||||
return parentId == other.parentId && localContext == other.localContext;
|
return parentType == other.parentType && localContext == other.localContext;
|
||||||
}
|
}
|
||||||
bool operator!=(const StructInstance &other) const noexcept
|
bool operator!=(const StructInstance &other) const noexcept
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -33,13 +33,13 @@ namespace Fig
|
|||||||
|
|
||||||
struct StructType
|
struct StructType
|
||||||
{
|
{
|
||||||
std::size_t id;
|
TypeInfo type;
|
||||||
ContextPtr defContext; // 定义时的上下文
|
ContextPtr defContext; // 定义时的上下文
|
||||||
std::vector<Field> fields;
|
std::vector<Field> fields;
|
||||||
|
|
||||||
// ===== Constructors =====
|
// ===== Constructors =====
|
||||||
StructType(ContextPtr _defContext, std::vector<Field> _fields) :
|
StructType(TypeInfo _type, ContextPtr _defContext, std::vector<Field> _fields) :
|
||||||
id(nextId()), defContext(std::move(_defContext)), fields(std::move(_fields)) {}
|
type(std::move(_type)), defContext(std::move(_defContext)), fields(std::move(_fields)) {}
|
||||||
|
|
||||||
StructType(const StructType &other) = default;
|
StructType(const StructType &other) = default;
|
||||||
StructType(StructType &&) noexcept = default;
|
StructType(StructType &&) noexcept = default;
|
||||||
@@ -49,7 +49,7 @@ namespace Fig
|
|||||||
// ===== Comparison =====
|
// ===== Comparison =====
|
||||||
bool operator==(const StructType &other) const noexcept
|
bool operator==(const StructType &other) const noexcept
|
||||||
{
|
{
|
||||||
return id == other.id;
|
return type == other.type;
|
||||||
}
|
}
|
||||||
bool operator!=(const StructType &other) const noexcept
|
bool operator!=(const StructType &other) const noexcept
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -58,12 +58,12 @@ namespace Fig
|
|||||||
return r;
|
return r;
|
||||||
};
|
};
|
||||||
const StructType &st = value->as<StructType>();
|
const StructType &st = value->as<StructType>();
|
||||||
return std::hash<std::size_t>{}(st.id) + HashFields(st.fields);
|
return std::hash<TypeInfo>{}(st.type) + HashFields(st.fields);
|
||||||
}
|
}
|
||||||
if (type == ValueType::StructInstance)
|
if (type == ValueType::StructInstance)
|
||||||
{
|
{
|
||||||
const StructInstance &si = value->as<StructInstance>();
|
const StructInstance &si = value->as<StructInstance>();
|
||||||
return std::hash<std::size_t>{}(si.parentId) + std::hash<uint64_t>{}(reinterpret_cast<uint64_t>(std::addressof(*si.localContext)));
|
return std::hash<TypeInfo>{}(si.parentType) + std::hash<uint64_t>{}(reinterpret_cast<uint64_t>(std::addressof(*si.localContext)));
|
||||||
}
|
}
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -400,11 +400,11 @@ namespace Fig
|
|||||||
static_cast<const void *>(&as<Function>())));
|
static_cast<const void *>(&as<Function>())));
|
||||||
if (is<StructType>())
|
if (is<StructType>())
|
||||||
return FString(std::format("<StructType {} at {:p}>",
|
return FString(std::format("<StructType {} at {:p}>",
|
||||||
as<StructType>().id,
|
as<StructType>().type.toString().toBasicString(),
|
||||||
static_cast<const void *>(&as<StructType>())));
|
static_cast<const void *>(&as<StructType>())));
|
||||||
if (is<StructInstance>())
|
if (is<StructInstance>())
|
||||||
return FString(std::format("<StructInstance '{}' at {:p}>",
|
return FString(std::format("<StructInstance '{}' at {:p}>",
|
||||||
as<StructInstance>().parentId,
|
as<StructInstance>().parentType.toString().toBasicString(),
|
||||||
static_cast<const void *>(&as<StructInstance>())));
|
static_cast<const void *>(&as<StructInstance>())));
|
||||||
if (is<List>())
|
if (is<List>())
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user