[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, FString> functionNames;
std::unordered_map<std::size_t, FString> structTypeNames;
// std::unordered_map<std::size_t, FString> structTypeNames;
public:
ContextPtr parent;
@@ -49,7 +49,7 @@ namespace Fig
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());
// structTypeNames.insert(c.structTypeNames.begin(), c.structTypeNames.end());
}
std::unordered_map<size_t, Function> getFunctions() const
@@ -142,11 +142,11 @@ namespace Fig
functions[fn.id] = fn;
functionNames[fn.id] = name;
}
if (ti == ValueType::StructType)
{
auto &st = value->as<StructType>();
structTypeNames[st.id] = name;
}
// if (ti == ValueType::StructType)
// {
// auto &st = value->as<StructType>();
// structTypeNames[st.id] = name;
// }
}
std::optional<Function> getFunction(std::size_t id)
{
@@ -180,22 +180,22 @@ namespace Fig
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->getStructName(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->getStructName(id);
// }
// else
// {
// return std::nullopt;
// }
// }
bool contains(const FString &name)
{
if (variables.contains(name))

View File

@@ -11,6 +11,20 @@
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)
{
const FString &name = var->name;
@@ -300,8 +314,7 @@ namespace Fig
LvObject lv = evalLv(lexp, ctx);
ObjectPtr rhs = eval(rexp, ctx);
lv.set(std::make_shared<Object>(
*(lv.get()) + *rhs
));
*(lv.get()) + *rhs));
return rhs;
}
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
ObjectPtr argVal = eval(fnArgs.argv[i], ctx);
TypeInfo actualType = argVal->getTypeInfo();
if (expectedType != actualType and expectedType != ValueType::Any)
if (!isTypeMatch(expectedType, argVal))
{
throw EvaluatorError(
u8"ArgumentTypeMismatchError",
@@ -457,7 +470,7 @@ namespace Fig
TypeInfo expectedType = fnParas.defParas[defParamIndex].second.first;
ObjectPtr defaultVal = eval(fnParas.defParas[defParamIndex].second.second, ctx);
if (expectedType != defaultVal->getTypeInfo() and expectedType != ValueType::Any)
if (!isTypeMatch(expectedType, defaultVal))
{
throw EvaluatorError(
u8"DefaultParameterTypeError",
@@ -471,7 +484,7 @@ namespace Fig
ObjectPtr argVal = eval(fnArgs.argv[i], ctx);
TypeInfo actualType = argVal->getTypeInfo();
if (expectedType != actualType and expectedType != ValueType::Any)
if (!isTypeMatch(expectedType, argVal))
{
throw EvaluatorError(
u8"ArgumentTypeMismatchError",
@@ -540,7 +553,7 @@ namespace Fig
break;
}
}
if (fnStruct.retType != retVal->getTypeInfo() and fnStruct.retType != ValueType::Any)
if (!isTypeMatch(fnStruct.retType, retVal))
{
throw EvaluatorError(
u8"ReturnTypeMismatchError",
@@ -728,7 +741,7 @@ namespace Fig
ObjectPtr defaultVal = eval(field.defaultValue, ctx); // it can't be null here
// type check
if (expectedType != defaultVal->getTypeInfo() && expectedType != ValueType::Any)
if (!isTypeMatch(expectedType, defaultVal))
{
throw EvaluatorError(
u8"StructFieldTypeMismatchError",
@@ -746,7 +759,7 @@ namespace Fig
}
const ObjectPtr &argVal = evaluatedArgs[i].second;
if (expectedType != argVal->getTypeInfo() && expectedType != ValueType::Any)
if (!isTypeMatch(expectedType, argVal))
{
throw EvaluatorError(
u8"StructFieldTypeMismatchError",
@@ -784,7 +797,7 @@ namespace Fig
// type check
const TypeInfo &expectedType = field.type;
if (expectedType != defaultVal->getTypeInfo() && expectedType != ValueType::Any)
if (!isTypeMatch(expectedType, defaultVal))
{
throw EvaluatorError(
u8"StructFieldTypeMismatchError",
@@ -801,7 +814,7 @@ namespace Fig
continue;
}
const ObjectPtr &argVal = evaluatedArgs[i].second;
if (field.type != argVal->getTypeInfo() && field.type != ValueType::Any)
if (!isTypeMatch(field.type, argVal))
{
throw EvaluatorError(
u8"StructFieldTypeMismatchError",
@@ -824,7 +837,7 @@ namespace Fig
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: {
@@ -905,7 +918,7 @@ namespace Fig
else if (!declaredTypeName.empty())
{
declaredType = TypeInfo(declaredTypeName);
if (value != nullptr && value->getTypeInfo() != declaredType && declaredType != ValueType::Any)
if (value != nullptr && !isTypeMatch(declaredType, value))
{
throw EvaluatorError(
u8"TypeError",
@@ -1006,12 +1019,13 @@ namespace Fig
}
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(
stDef->name,
ValueType::StructType,
am,
std::make_shared<Object>(StructType(
type,
defContext,
fields)));
return StatementResult::normal();

View File

@@ -6,7 +6,6 @@
#include <Value/LvObject.hpp>
#include <filesystem>
namespace Fig
{
struct StatementResult
@@ -52,6 +51,7 @@ namespace Fig
{
private:
ContextPtr global;
public:
FString sourcePath;
@@ -84,8 +84,7 @@ namespace Fig
name,
ValueType::Function,
AccessModifier::Const,
std::make_shared<Object>(f)
);
std::make_shared<Object>(f));
}
}
@@ -102,24 +101,27 @@ namespace Fig
val);
}
}
bool isTypeMatch(const TypeInfo &, ObjectPtr);
/* Left-value eval*/
LvObject evalVarExpr(Ast::VarExpr, ContextPtr);
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]
/* Right-value eval*/
RvObject evalBinary(Ast::BinaryExpr, ContextPtr); // normal binary expr: +, -, *....
RvObject evalUnary(Ast::UnaryExpr, ContextPtr); // unary expr
RvObject evalBinary(Ast::BinaryExpr, ContextPtr); // normal binary expr: +, -, *....
RvObject evalUnary(Ast::UnaryExpr, ContextPtr); // unary 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);
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> &);
ContextPtr loadModule(const std::filesystem::path &);

View File

@@ -75,7 +75,8 @@ namespace Fig
{FString(u8"else"), TokenType::Else},
{FString(u8"struct"), TokenType::Struct},
{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"return"), TokenType::Return},
{FString(u8"break"), TokenType::Break},

View File

@@ -18,14 +18,14 @@ namespace Fig
Identifier,
/* Keywords */
Package, // package
And, // and
Or, // or
Not, // not
Import, // import
Function, // func
Variable, // var
Const, // const
Package, // package
And, // and
Or, // or
Not, // not
Import, // import
Function, // func
Variable, // var
Const, // const
// Final, // final
While, // while
For, // for
@@ -33,7 +33,8 @@ namespace Fig
Else, // else
Struct, // struct
Interface, // interface
Implement, // implement
Implement, // impl
Is, // is
Public, // public
Return, // return
Break, // break
@@ -64,7 +65,7 @@ namespace Fig
ShiftLeft, // <<
ShiftRight, // >>
// Exclamation, // !
Question, // ?
Question, // ?
Assign, // =
Less, // <
Greater, // >
@@ -87,8 +88,8 @@ namespace Fig
LeftBrace, // {
RightBrace, // }
// LeftArrow, // <-
RightArrow, // ->
DoubleArrow, // =>
RightArrow, // ->
DoubleArrow, // =>
Equal, // ==
NotEqual, // !=
LessEqual, // <=
@@ -106,7 +107,7 @@ namespace Fig
Walrus, // :=
Power, // **
TripleDot, // ... for variadic parameter
TripleDot, // ... for variadic parameter
};
class Token final

View File

@@ -77,3 +77,16 @@ namespace Fig
using StringClass = FString;
}; // namespace ValueType
}; // 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
#include <Context/context_forward.hpp>
#include <Value/Type.hpp>
namespace Fig
{
struct StructInstance
{
size_t parentId;
TypeInfo parentType;
ContextPtr localContext;
// ===== Constructors =====
StructInstance(size_t _parentId, ContextPtr _localContext) :
parentId(_parentId), localContext(std::move(_localContext)) {}
StructInstance(TypeInfo _parentType, ContextPtr _localContext) :
parentType(_parentType), localContext(std::move(_localContext)) {}
StructInstance(const StructInstance &other) = default;
StructInstance(StructInstance &&) noexcept = default;
@@ -21,7 +22,7 @@ namespace Fig
// ===== Comparison =====
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
{

View File

@@ -33,13 +33,13 @@ namespace Fig
struct StructType
{
std::size_t id;
TypeInfo type;
ContextPtr defContext; // 定义时的上下文
std::vector<Field> fields;
// ===== Constructors =====
StructType(ContextPtr _defContext, std::vector<Field> _fields) :
id(nextId()), defContext(std::move(_defContext)), fields(std::move(_fields)) {}
StructType(TypeInfo _type, ContextPtr _defContext, std::vector<Field> _fields) :
type(std::move(_type)), defContext(std::move(_defContext)), fields(std::move(_fields)) {}
StructType(const StructType &other) = default;
StructType(StructType &&) noexcept = default;
@@ -49,7 +49,7 @@ namespace Fig
// ===== Comparison =====
bool operator==(const StructType &other) const noexcept
{
return id == other.id;
return type == other.type;
}
bool operator!=(const StructType &other) const noexcept
{

View File

@@ -58,12 +58,12 @@ namespace Fig
return r;
};
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)
{
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);
}

View File

@@ -400,11 +400,11 @@ namespace Fig
static_cast<const void *>(&as<Function>())));
if (is<StructType>())
return FString(std::format("<StructType {} at {:p}>",
as<StructType>().id,
as<StructType>().type.toString().toBasicString(),
static_cast<const void *>(&as<StructType>())));
if (is<StructInstance>())
return FString(std::format("<StructInstance '{}' at {:p}>",
as<StructInstance>().parentId,
as<StructInstance>().parentType.toString().toBasicString(),
static_cast<const void *>(&as<StructInstance>())));
if (is<List>())
{