[Impl] StructInstance现在记录parent TypeInfo, StructType改用TypeInfo

This commit is contained in:
2025-12-29 20:21:12 +08:00
parent 92dcd19f39
commit 31c2ae4d84
10 changed files with 105 additions and 73 deletions

View File

@@ -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))

View File

@@ -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();

View File

@@ -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,24 +101,27 @@ 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
LvObject evalIndexExpr(Ast::IndexExpr, ContextPtr); // a[b] LvObject evalIndexExpr(Ast::IndexExpr, ContextPtr); // a[b]
LvObject evalLv(Ast::Expression, ContextPtr); // for access: a.b / index a[b] LvObject evalLv(Ast::Expression, ContextPtr); // for access: a.b / index a[b]
/* Right-value eval*/ /* Right-value eval*/
RvObject evalBinary(Ast::BinaryExpr, ContextPtr); // normal binary expr: +, -, *.... RvObject evalBinary(Ast::BinaryExpr, ContextPtr); // normal binary expr: +, -, *....
RvObject evalUnary(Ast::UnaryExpr, ContextPtr); // unary expr RvObject evalUnary(Ast::UnaryExpr, ContextPtr); // unary expr
RvObject evalTernary(Ast::TernaryExpr, ContextPtr); // ternary expr RvObject evalTernary(Ast::TernaryExpr, ContextPtr); // ternary expr
RvObject evalFunctionCall(const Function&, const Ast::FunctionArguments&, const FString& ,ContextPtr); // function call RvObject evalFunctionCall(const Function &, const Ast::FunctionArguments &, const FString &, ContextPtr); // function call
RvObject eval(Ast::Expression, ContextPtr); RvObject eval(Ast::Expression, ContextPtr);
StatementResult evalBlockStatement(Ast::BlockStatement, ContextPtr); // block StatementResult evalBlockStatement(Ast::BlockStatement, ContextPtr); // block
StatementResult evalStatement(Ast::Statement, ContextPtr); // statement StatementResult evalStatement(Ast::Statement, ContextPtr); // statement
std::filesystem::path resolveModulePath(const std::vector<FString> &); std::filesystem::path resolveModulePath(const std::vector<FString> &);
ContextPtr loadModule(const std::filesystem::path &); ContextPtr loadModule(const std::filesystem::path &);

View File

@@ -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},

View File

@@ -18,14 +18,14 @@ namespace Fig
Identifier, Identifier,
/* Keywords */ /* Keywords */
Package, // package Package, // package
And, // and And, // and
Or, // or Or, // or
Not, // not Not, // not
Import, // import Import, // import
Function, // func Function, // func
Variable, // var Variable, // var
Const, // const Const, // const
// Final, // final // Final, // final
While, // while While, // while
For, // for For, // for
@@ -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
@@ -64,7 +65,7 @@ namespace Fig
ShiftLeft, // << ShiftLeft, // <<
ShiftRight, // >> ShiftRight, // >>
// Exclamation, // ! // Exclamation, // !
Question, // ? Question, // ?
Assign, // = Assign, // =
Less, // < Less, // <
Greater, // > Greater, // >
@@ -87,8 +88,8 @@ namespace Fig
LeftBrace, // { LeftBrace, // {
RightBrace, // } RightBrace, // }
// LeftArrow, // <- // LeftArrow, // <-
RightArrow, // -> RightArrow, // ->
DoubleArrow, // => DoubleArrow, // =>
Equal, // == Equal, // ==
NotEqual, // != NotEqual, // !=
LessEqual, // <= LessEqual, // <=
@@ -106,7 +107,7 @@ namespace Fig
Walrus, // := Walrus, // :=
Power, // ** Power, // **
TripleDot, // ... for variadic parameter TripleDot, // ... for variadic parameter
}; };
class Token final class Token final

View File

@@ -76,4 +76,17 @@ namespace Fig
using NullClass = std::monostate; using NullClass = std::monostate;
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());
}
};
};

View File

@@ -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
{ {

View File

@@ -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
{ {

View File

@@ -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);
} }

View File

@@ -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>())
{ {