From 31c2ae4d844c79d7c427a50f74a750b8f0a13a43 Mon Sep 17 00:00:00 2001 From: PuqiAR Date: Mon, 29 Dec 2025 20:21:12 +0800 Subject: [PATCH] =?UTF-8?q?[Impl]=20StructInstance=E7=8E=B0=E5=9C=A8?= =?UTF-8?q?=E8=AE=B0=E5=BD=95parent=20TypeInfo,=20StructType=E6=94=B9?= =?UTF-8?q?=E7=94=A8TypeInfo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Context/context.hpp | 46 ++++++++++++++++++------------------ src/Evaluator/evaluator.cpp | 40 +++++++++++++++++++++---------- src/Evaluator/evaluator.hpp | 22 +++++++++-------- src/Lexer/lexer.cpp | 3 ++- src/Token/token.hpp | 27 +++++++++++---------- src/Value/Type.hpp | 15 +++++++++++- src/Value/structInstance.hpp | 9 +++---- src/Value/structType.hpp | 8 +++---- src/Value/value.cpp | 4 ++-- src/Value/value.hpp | 4 ++-- 10 files changed, 105 insertions(+), 73 deletions(-) diff --git a/src/Context/context.hpp b/src/Context/context.hpp index 925d523..1c87db9 100644 --- a/src/Context/context.hpp +++ b/src/Context/context.hpp @@ -20,7 +20,7 @@ namespace Fig std::unordered_map functions; std::unordered_map functionNames; - std::unordered_map structTypeNames; + // std::unordered_map 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 getFunctions() const @@ -142,11 +142,11 @@ namespace Fig functions[fn.id] = fn; functionNames[fn.id] = name; } - if (ti == ValueType::StructType) - { - auto &st = value->as(); - structTypeNames[st.id] = name; - } + // if (ti == ValueType::StructType) + // { + // auto &st = value->as(); + // structTypeNames[st.id] = name; + // } } std::optional getFunction(std::size_t id) { @@ -180,22 +180,22 @@ namespace Fig return std::nullopt; } } - std::optional 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 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)) diff --git a/src/Evaluator/evaluator.cpp b/src/Evaluator/evaluator.cpp index 717fdd3..fb8b98c 100644 --- a/src/Evaluator/evaluator.cpp +++ b/src/Evaluator/evaluator.cpp @@ -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(); + 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( - *(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(StructInstance(structT.id, instanceCtx)); + return std::make_shared(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(StructType( + type, defContext, fields))); return StatementResult::normal(); diff --git a/src/Evaluator/evaluator.hpp b/src/Evaluator/evaluator.hpp index c8cea2d..6d18b05 100644 --- a/src/Evaluator/evaluator.hpp +++ b/src/Evaluator/evaluator.hpp @@ -6,7 +6,6 @@ #include #include - 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(f) - ); + std::make_shared(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 &); ContextPtr loadModule(const std::filesystem::path &); diff --git a/src/Lexer/lexer.cpp b/src/Lexer/lexer.cpp index 52fa2a0..5f65532 100644 --- a/src/Lexer/lexer.cpp +++ b/src/Lexer/lexer.cpp @@ -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}, diff --git a/src/Token/token.hpp b/src/Token/token.hpp index 5a02277..012c8ee 100644 --- a/src/Token/token.hpp +++ b/src/Token/token.hpp @@ -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 diff --git a/src/Value/Type.hpp b/src/Value/Type.hpp index 6622e28..879a624 100644 --- a/src/Value/Type.hpp +++ b/src/Value/Type.hpp @@ -76,4 +76,17 @@ namespace Fig using NullClass = std::monostate; using StringClass = FString; }; // namespace ValueType -}; // namespace Fig \ No newline at end of file +}; // namespace Fig + + +namespace std +{ + template <> + struct hash + { + size_t operator()(const Fig::TypeInfo &t) + { + return std::hash{}(t.getInstanceID()); + } + }; +}; \ No newline at end of file diff --git a/src/Value/structInstance.hpp b/src/Value/structInstance.hpp index 29f5c31..7d12dd0 100644 --- a/src/Value/structInstance.hpp +++ b/src/Value/structInstance.hpp @@ -1,17 +1,18 @@ #pragma once #include +#include 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 { diff --git a/src/Value/structType.hpp b/src/Value/structType.hpp index fe5b79c..ca369f5 100644 --- a/src/Value/structType.hpp +++ b/src/Value/structType.hpp @@ -33,13 +33,13 @@ namespace Fig struct StructType { - std::size_t id; + TypeInfo type; ContextPtr defContext; // 定义时的上下文 std::vector fields; // ===== Constructors ===== - StructType(ContextPtr _defContext, std::vector _fields) : - id(nextId()), defContext(std::move(_defContext)), fields(std::move(_fields)) {} + StructType(TypeInfo _type, ContextPtr _defContext, std::vector _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 { diff --git a/src/Value/value.cpp b/src/Value/value.cpp index b062331..d656fda 100644 --- a/src/Value/value.cpp +++ b/src/Value/value.cpp @@ -58,12 +58,12 @@ namespace Fig return r; }; const StructType &st = value->as(); - return std::hash{}(st.id) + HashFields(st.fields); + return std::hash{}(st.type) + HashFields(st.fields); } if (type == ValueType::StructInstance) { const StructInstance &si = value->as(); - return std::hash{}(si.parentId) + std::hash{}(reinterpret_cast(std::addressof(*si.localContext))); + return std::hash{}(si.parentType) + std::hash{}(reinterpret_cast(std::addressof(*si.localContext))); } assert(false); } diff --git a/src/Value/value.hpp b/src/Value/value.hpp index d3fb0e9..db1c023 100644 --- a/src/Value/value.hpp +++ b/src/Value/value.hpp @@ -400,11 +400,11 @@ namespace Fig static_cast(&as()))); if (is()) return FString(std::format("", - as().id, + as().type.toString().toBasicString(), static_cast(&as()))); if (is()) return FString(std::format("", - as().parentId, + as().parentType.toString().toBasicString(), static_cast(&as()))); if (is()) {