From 4535f7505862bb9da4690ae43f121fc17f7da337 Mon Sep 17 00:00:00 2001 From: PuqiAR Date: Tue, 3 Feb 2026 18:49:40 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E8=B0=83=E7=94=A8=E6=97=B6=E6=B1=82=E5=80=BC=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E7=9A=84=E4=BD=9C=E7=94=A8=E5=9F=9F=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E7=9A=84=E9=97=AE=E9=A2=98=E3=80=82=E7=BB=93=E6=9E=84?= =?UTF-8?q?=E4=BD=93=E4=B8=AD=E7=8E=B0=E5=9C=A8=E5=8F=AF=E4=BB=A5=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E8=87=AA=E5=B7=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ExampleCodes/use_std_time.fig | 29 +++++++++++ src/Evaluator/Context/context.hpp | 25 +++------ src/Evaluator/Core/EvalFunctionCall.cpp | 18 +++---- src/Evaluator/Core/EvalInitExpr.cpp | 2 +- src/Evaluator/Core/EvalLvObject.cpp | 48 +++++++++++++++++ src/Evaluator/Core/EvalStatement.cpp | 29 ++++++----- src/Evaluator/evaluator.cpp | 52 ++++++++++++++++--- .../std/{tester/tester.fig => test/test.fig} | 4 +- src/Module/Library/std/time/time.fig | 11 ++++ 9 files changed, 169 insertions(+), 49 deletions(-) create mode 100644 ExampleCodes/use_std_time.fig rename src/Module/Library/std/{tester/tester.fig => test/test.fig} (96%) diff --git a/ExampleCodes/use_std_time.fig b/ExampleCodes/use_std_time.fig new file mode 100644 index 0000000..400bd67 --- /dev/null +++ b/ExampleCodes/use_std_time.fig @@ -0,0 +1,29 @@ +import std.io; +import std.test; + +var ascii_string_test := new test.Test{ + "ascii_string_test", + func () => io.println("Hello," + " world!"), + 2 +}; + +var unicode_string_test := new test.Test{ + "unicode_string_test", + func () => io.println("你好," + " 世界!"), + 2 +}; + +var unicode_string_inserting_test := new test.Test{ + "unicode_string_inserting_test", + func (){ + var str := "我是你的粑粑"; + str.insert(1, "不"); + return str; + }, + "我不是你的粑粑" +}; + +var tests := [ascii_string_test, unicode_string_test, unicode_string_inserting_test]; + +var tester := new test.Tester{tests}; +tester.TestAll(); \ No newline at end of file diff --git a/src/Evaluator/Context/context.hpp b/src/Evaluator/Context/context.hpp index 8c4a907..6262f58 100644 --- a/src/Evaluator/Context/context.hpp +++ b/src/Evaluator/Context/context.hpp @@ -30,31 +30,19 @@ namespace Fig struct OperationRecord { - using UnaryOpFn = std::function; + using UnaryOpFn = std::function; using BinaryOpFn = std::function; std::unordered_map unOpRec; std::unordered_map binOpRec; - bool hasUnaryOp(Ast::Operator op) const - { - return unOpRec.contains(op); - } + bool hasUnaryOp(Ast::Operator op) const { return unOpRec.contains(op); } - bool hasBinaryOp(Ast::Operator op) const - { - return binOpRec.contains(op); - } + bool hasBinaryOp(Ast::Operator op) const { return binOpRec.contains(op); } - const UnaryOpFn &getUnaryOpFn(Ast::Operator op) const - { - return unOpRec.at(op); - } + const UnaryOpFn &getUnaryOpFn(Ast::Operator op) const { return unOpRec.at(op); } - const BinaryOpFn &getBinaryOpFn(Ast::Operator op) const - { - return binOpRec.at(op); - } + const BinaryOpFn &getBinaryOpFn(Ast::Operator op) const { return binOpRec.at(op); } }; class Context : public std::enable_shared_from_this @@ -69,6 +57,7 @@ namespace Fig // implRegistry std::unordered_map, TypeInfoHash> implRegistry; std::unordered_map opRegistry; + public: ContextPtr parent; @@ -394,6 +383,8 @@ namespace Fig throw ""; // ignore warning } + std::unordered_map &getOpRegistry() { return opRegistry; } + bool hasOperatorImplemented(const TypeInfo &type, Ast::Operator op, bool isUnary = false) const { auto it = opRegistry.find(type); diff --git a/src/Evaluator/Core/EvalFunctionCall.cpp b/src/Evaluator/Core/EvalFunctionCall.cpp index f53f5ef..df6a1fb 100644 --- a/src/Evaluator/Core/EvalFunctionCall.cpp +++ b/src/Evaluator/Core/EvalFunctionCall.cpp @@ -96,11 +96,11 @@ namespace Fig size_t i; for (i = 0; i < fnParas.posParas.size(); i++) { - const TypeInfo &expectedType = actualType(eval(fnParas.posParas[i].second, ctx)); // look up type info, if exists a type + const TypeInfo &expectedType = actualType(eval(fnParas.posParas[i].second, fn.closureContext)); // 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 (!isTypeMatch(expectedType, argVal, ctx)) + if (!isTypeMatch(expectedType, argVal, fn.closureContext)) { throw EvaluatorError(u8"ArgumentTypeMismatchError", std::format("In function '{}', argument '{}' expects type '{}', but got type '{}'", @@ -116,10 +116,10 @@ namespace Fig for (; i < fnArgs.getLength(); i++) { size_t defParamIndex = i - fnParas.posParas.size(); - const TypeInfo &expectedType = actualType(eval(fnParas.defParas[defParamIndex].second.first, ctx)); + const TypeInfo &expectedType = actualType(eval(fnParas.defParas[defParamIndex].second.first, fn.closureContext)); - ObjectPtr defaultVal = eval(fnParas.defParas[defParamIndex].second.second, ctx); - if (!isTypeMatch(expectedType, defaultVal, ctx)) + ObjectPtr defaultVal = eval(fnParas.defParas[defParamIndex].second.second, fn.closureContext); + if (!isTypeMatch(expectedType, defaultVal, fn.closureContext)) { throw EvaluatorError( u8"DefaultParameterTypeError", @@ -134,7 +134,7 @@ namespace Fig ObjectPtr argVal = eval(fnArgs.argv[i], ctx); TypeInfo actualType = argVal->getTypeInfo(); - if (!isTypeMatch(expectedType, argVal, ctx)) + if (!isTypeMatch(expectedType, argVal, fn.closureContext)) { throw EvaluatorError(u8"ArgumentTypeMismatchError", std::format("In function '{}', argument '{}' expects type '{}', but got type '{}'", @@ -150,7 +150,7 @@ namespace Fig for (; i < fnParas.size(); i++) { size_t defParamIndex = i - fnParas.posParas.size(); - ObjectPtr defaultVal = eval(fnParas.defParas[defParamIndex].second.second, ctx); + ObjectPtr defaultVal = eval(fnParas.defParas[defParamIndex].second.second, fn.closureContext); evaluatedArgs.argv.push_back(defaultVal); } @@ -162,13 +162,13 @@ namespace Fig if (j < fnParas.posParas.size()) { paramName = fnParas.posParas[j].first; - paramType = actualType(eval(fnParas.posParas[j].second, ctx)); + paramType = actualType(eval(fnParas.posParas[j].second, fn.closureContext)); } else { size_t defParamIndex = j - fnParas.posParas.size(); paramName = fnParas.defParas[defParamIndex].first; - paramType = actualType(eval(fnParas.defParas[defParamIndex].second.first, ctx)); + paramType = actualType(eval(fnParas.defParas[defParamIndex].second.first, fn.closureContext)); } AccessModifier argAm = AccessModifier::Normal; newContext->def(paramName, paramType, argAm, evaluatedArgs.argv[j]); diff --git a/src/Evaluator/Core/EvalInitExpr.cpp b/src/Evaluator/Core/EvalInitExpr.cpp index 24a5136..197748a 100644 --- a/src/Evaluator/Core/EvalInitExpr.cpp +++ b/src/Evaluator/Core/EvalInitExpr.cpp @@ -158,7 +158,7 @@ namespace Fig }; ContextPtr instanceCtx = - std::make_shared(FString(std::format("", structName.toBasicString())), ctx); + std::make_shared(FString(std::format("", structName.toBasicString())), defContext); /* 3 ways of calling constructor .1 Person {"Fig", 1, "IDK"}; diff --git a/src/Evaluator/Core/EvalLvObject.cpp b/src/Evaluator/Core/EvalLvObject.cpp index c4e18a8..e666c9f 100644 --- a/src/Evaluator/Core/EvalLvObject.cpp +++ b/src/Evaluator/Core/EvalLvObject.cpp @@ -8,6 +8,35 @@ namespace Fig LvObject Evaluator::evalVarExpr(Ast::VarExpr var, ContextPtr ctx) { const FString &name = var->name; + + // 调试信息 + // std::cerr << "=== DEBUG evalVarExpr ===" << std::endl; + // std::cerr << "Looking for: " << name.toBasicString() << std::endl; + // std::cerr << "Context: " << ctx->getScopeName().toBasicString() << std::endl; + + // // 打印上下文 + // ContextPtr current = ctx; + // int depth = 0; + // while (current) + // { + // std::cerr << " [" << depth << "] " << current->getScopeName().toBasicString(); + // if (current->containsInThisScope(name)) + // { + // std::cerr << " -> FOUND HERE!" << std::endl; + // auto slot = current->get(name); + // std::cerr << " Type: " << slot->declaredType.toString().toBasicString() << std::endl; + // std::cerr << " Value: " << (slot->value ? slot->value->toString().toBasicString() : "null") + // << std::endl; + // } + // else + // { + // std::cerr << " -> not found" << std::endl; + // } + // current = current->parent; + // depth++; + // } + // end + if (!ctx->contains(name)) { throw EvaluatorError(u8"UndeclaredIdentifierError", name, var); } return LvObject(ctx->get(name), ctx); } @@ -18,7 +47,26 @@ namespace Fig const FString &member = me->member; if (baseVal->getTypeInfo() == ValueType::Module) { + // std::cerr << "=== DEBUG evalMemberExpr (Module) ===" << std::endl; + // std::cerr << "Module object: " << baseVal->toString().toBasicString() << std::endl; + const Module &mod = baseVal->as(); + // std::cerr << "Module context: " << mod.ctx->getScopeName().toBasicString() << std::endl; + // std::cerr << "Looking for member: " << member.toBasicString() << std::endl; + + // if (mod.ctx->contains(member)) + // { + // std::cerr << "Found in module context!" << std::endl; + // if (mod.ctx->isVariablePublic(member)) { std::cerr << "And it's public!" << std::endl; } + // else + // { + // std::cerr << "But it's NOT public!" << std::endl; + // } + // } + // else + // { + // std::cerr << "NOT found in module context!" << std::endl; + // } if (mod.ctx->contains(member) && mod.ctx->isVariablePublic(member)) { return LvObject(mod.ctx->get(member), ctx); diff --git a/src/Evaluator/Core/EvalStatement.cpp b/src/Evaluator/Core/EvalStatement.cpp index 9f34ce9..ad6a293 100644 --- a/src/Evaluator/Core/EvalStatement.cpp +++ b/src/Evaluator/Core/EvalStatement.cpp @@ -4,6 +4,7 @@ #include "Ast/functionParameters.hpp" #include "Core/fig_string.hpp" #include "Evaluator/Core/StatementResult.hpp" +#include "Evaluator/Value/Type.hpp" #include "Evaluator/Value/value.hpp" #include #include @@ -103,6 +104,20 @@ namespace Fig std::format("Structure '{}' already defined in this scope", stDef->name.toBasicString()), stDef); } + + TypeInfo type(stDef->name, true); // register type name + ContextPtr defContext = std::make_shared(FString(std::format("", + stDef->name.toBasicString(), + stDef->getAAI().line, + stDef->getAAI().column)), + ctx); + ObjectPtr structTypeObj = std::make_shared(StructType(type, defContext, {})); + + AccessModifier am = (stDef->isPublic ? AccessModifier::PublicConst : AccessModifier::Const); + + ctx->def(stDef->name, ValueType::StructType, am, structTypeObj); // predef + defContext->def(stDef->name, ValueType::StructType, AccessModifier::Const, structTypeObj); // predef to itself, always const + std::vector fields; std::vector _fieldNames; for (Ast::StructDefField field : stDef->fields) @@ -124,11 +139,8 @@ namespace Fig fields.push_back(Field(field.am, field.fieldName, fieldType, field.defaultValueExpr)); } - ContextPtr defContext = std::make_shared(FString(std::format("", - stDef->name.toBasicString(), - stDef->getAAI().line, - stDef->getAAI().column)), - ctx); + structTypeObj->as().fields = fields; + const Ast::BlockStatement &body = stDef->body; for (auto &st : body->stmts) { @@ -141,13 +153,6 @@ namespace Fig } evalStatement(st, defContext); // function def st } - - AccessModifier am = (stDef->isPublic ? AccessModifier::PublicConst : AccessModifier::Const); - 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.cpp b/src/Evaluator/evaluator.cpp index f6057c5..82db4bf 100644 --- a/src/Evaluator/evaluator.cpp +++ b/src/Evaluator/evaluator.cpp @@ -1,3 +1,7 @@ +#include "Ast/astBase.hpp" +#include "Core/fig_string.hpp" +#include "Evaluator/Core/StatementResult.hpp" +#include "Evaluator/Value/value.hpp" #include #include @@ -7,6 +11,7 @@ #include #include #include +#include #ifndef SourceInfo #define SourceInfo(ptr) (ptr->sourcePath), (ptr->sourceLines) @@ -34,20 +39,36 @@ namespace Fig ContextPtr Evaluator::loadModule(const std::filesystem::path &path) { + static std::unordered_map, std::vector>> mod_ast_cache{}; + FString modSourcePath(path.string()); + std::ifstream file(path); assert(file.is_open()); - std::string source((std::istreambuf_iterator(file)), std::istreambuf_iterator()); - file.close(); - - std::vector modSourceLines = Utils::splitSource(FString(source)); - - Lexer lexer((FString(source)), modSourcePath, modSourceLines); - Parser parser(lexer, modSourcePath, modSourceLines); std::vector asts; - asts = parser.parseAll(); + std::vector modSourceLines; + + if (mod_ast_cache.contains(modSourcePath)) + { + auto &[_sl, _asts] = mod_ast_cache[modSourcePath]; + modSourceLines = _sl; + asts = _asts; + } + else + { + std::string source((std::istreambuf_iterator(file)), std::istreambuf_iterator()); + file.close(); + + modSourceLines = Utils::splitSource(FString(source)); + + Lexer lexer((FString(source)), modSourcePath, modSourceLines); + Parser parser(lexer, modSourcePath, modSourceLines); + + asts = parser.parseAll(); + mod_ast_cache[modSourcePath] = {modSourceLines, asts}; + } Evaluator evaluator; evaluator.SetSourcePath(modSourcePath); @@ -77,6 +98,21 @@ namespace Fig ctx->getImplRegistry().insert(modCtx->getImplRegistry().begin(), modCtx->getImplRegistry().end()); // load impl + for (auto &[type, opRecord] : modCtx->getOpRegistry()) + { + if (ctx->getOpRegistry().contains(type)) + { + throw EvaluatorError( + u8"DuplicateOperationOverload", + std::format("Module `{}` and current context `{}` have conflict operation overload for `{}` object", + modCtx->getScopeName().toBasicString(), + ctx->getScopeName().toBasicString(), + type.toString().toBasicString()), + i); + } + ctx->getOpRegistry()[type] = opRecord; + } + // std::cerr << modName.toBasicString() << '\n'; DEBUG if (ctx->containsInThisScope(modName)) diff --git a/src/Module/Library/std/tester/tester.fig b/src/Module/Library/std/test/test.fig similarity index 96% rename from src/Module/Library/std/tester/tester.fig rename to src/Module/Library/std/test/test.fig index 1257d47..6092753 100644 --- a/src/Module/Library/std/tester/tester.fig +++ b/src/Module/Library/std/test/test.fig @@ -1,6 +1,6 @@ /* - Official Module `std.tester` - Library/std/tester/tester.fig + Official Module `std.test` + Library/std/test/test.fig Copyright © 2025 PuqiAR. All rights reserved. */ diff --git a/src/Module/Library/std/time/time.fig b/src/Module/Library/std/time/time.fig index e1346a0..cd4fa6c 100644 --- a/src/Module/Library/std/time/time.fig +++ b/src/Module/Library/std/time/time.fig @@ -43,8 +43,19 @@ public struct Time return result; } // TODO: support `-` operator when Fig supports overload + // supported now! 26-2-2. PuqiAR } +impl Operation for Time +{ + Sub(l: Time, r: Time) + { + return new Time{ + l.since(r) + }; + } +} + public func now() -> Time { return new Time{__ftime_now_ns()};