From 41bff72d4420397386ff0a88f5b53d84c0f51d20 Mon Sep 17 00:00:00 2001 From: PuqiAR Date: Sun, 1 Feb 2026 20:01:59 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=99=E6=98=AF=E4=B8=80=E6=9D=A1=20msg.=20(?= =?UTF-8?q?=20=E6=AD=A3=E6=96=87=EF=BC=9Aerror=20log=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E3=80=82=E6=96=B0=E5=A2=9Estd.tester=E3=80=82parser=20preceden?= =?UTF-8?q?ce=E9=87=8D=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Error/errorLog.hpp | 30 +++++--- src/Evaluator/Value/value.hpp | 2 +- src/Module/Library/std/std.fig | 3 +- src/Module/Library/std/tester/tester.fig | 86 ++++++++++++++++++++++ src/Module/builtins.cpp | 4 +- src/Parser/parser.cpp | 91 +++++++++++++----------- 6 files changed, 163 insertions(+), 53 deletions(-) create mode 100644 src/Module/Library/std/tester/tester.fig diff --git a/src/Error/errorLog.hpp b/src/Error/errorLog.hpp index d615e2d..a019fb4 100644 --- a/src/Error/errorLog.hpp +++ b/src/Error/errorLog.hpp @@ -110,21 +110,31 @@ namespace Fig coloredPrint(TC::LightRed, "✖ "); coloredPrint(TC::LightRed, std::format("{}: {}\n", err.getErrorType().toBasicString(), FString(err.getMessage()).toBasicString())); coloredPrint(TC::White, std::format(" at {}:{} in file '{}'\n", err.getLine(), err.getColumn(), fileName.toBasicString())); - FString lineContent = ((int64_t(err.getLine()) - int64_t(1)) >= 0 ? sourceLines[err.getLine() - 1] : u8""); - coloredPrint(TC::LightBlue, std::format(" {}\n", lineContent.toBasicString())); + + FString lineContent; FString pointerLine; - for (size_t i = 1; i < err.getColumn(); ++i) + + if (fileName != u8"") { - if (lineContent[i - 1] == U'\t') + lineContent = ((int64_t(err.getLine()) - int64_t(1)) >= 0 ? sourceLines[err.getLine() - 1] : u8""); + FString pointerLine; + for (size_t i = 1; i < err.getColumn(); ++i) { - pointerLine += U'\t'; - } - else - { - pointerLine += U' '; + if (lineContent[i - 1] == U'\t') { pointerLine += U'\t'; } + else + { + pointerLine += U' '; + } } + pointerLine += U'^'; } - pointerLine += U'^'; + else + { + lineContent = fileName; + } + + coloredPrint(TC::LightBlue, std::format(" {}\n", lineContent.toBasicString())); + coloredPrint(TC::LightGreen, std::format(" {}\n", pointerLine.toBasicString())); coloredPrint(TC::DarkGray, std::format("🔧 in function '{}' ({}:{})\n", err.src_loc.function_name(), err.src_loc.file_name(), err.src_loc.line())); } diff --git a/src/Evaluator/Value/value.hpp b/src/Evaluator/Value/value.hpp index ee8b472..0f6819b 100644 --- a/src/Evaluator/Value/value.hpp +++ b/src/Evaluator/Value/value.hpp @@ -429,7 +429,7 @@ namespace Fig { if (is()) return FString(u8"null"); if (is()) return FString(std::to_string(as())); - if (is()) return FString(std::format("{:g}", as())); + if (is()) return FString(std::format("{}", as())); if (is()) return FString(u8"\"" + as() + u8"\""); if (is()) return as() ? FString(u8"true") : FString(u8"false"); if (is()) diff --git a/src/Module/Library/std/std.fig b/src/Module/Library/std/std.fig index a1b3667..571cff5 100644 --- a/src/Module/Library/std/std.fig +++ b/src/Module/Library/std/std.fig @@ -5,4 +5,5 @@ import io; // link std.io import value; // link std.type -import math; // link std.math \ No newline at end of file +import math; // link std.math +import tester; // link std.tester \ No newline at end of file diff --git a/src/Module/Library/std/tester/tester.fig b/src/Module/Library/std/tester/tester.fig new file mode 100644 index 0000000..1257d47 --- /dev/null +++ b/src/Module/Library/std/tester/tester.fig @@ -0,0 +1,86 @@ +/* + Official Module `std.tester` + Library/std/tester/tester.fig + + Copyright © 2025 PuqiAR. All rights reserved. +*/ + + + +import std.time; +import std.io; + +// import std.value; +// import std.math; +// import std.formater; + +// const library_load_time := time.now(); +// io.println("All std libraries loaded! Cost:", library_load_time.toSeconds(), "s\n"); + +public struct Test +{ + public case: String; + public fn: Function; + public expect_result: Any; + + public func Run() + { + const start := time.now(); + const result := fn(); + const end := time.now(); + + const duration := new time.Time{ end.since(start) }; + + if result != expect_result + { + io.println("❌ Test '" + case + "'" + " failed"); + io.println(" expect", expect_result, ", got", result); + + return 1; + } + else + { + io.println("✔ Test '" + case + "'" + " succeed"); + io.println(" result:", result); + + return 0; + } + } +} + +public struct Tester +{ + public tests: List = []; + + public func AddTest(test: Test) + { + tests.push(test); + } + + public func TestAll() + { + const numtests := tests.length(); + + var success := 0; + var fail := 0; + + for var i := 0; i < numtests; i += 1 + { + io.printf("({}/{})", i + 1, numtests); + var result := tests[i].Run(); + if result == 0 + { + success += 1; + } + else + { + fail += 1; + } + } + io.println(); + io.println("=" * 100); + io.println("All tests executed"); + io.printf(" ({}/{}) success tested!\n", success, numtests); + io.printf(" ({}/{}) failed!\n", fail, numtests); + } +} \ No newline at end of file diff --git a/src/Module/builtins.cpp b/src/Module/builtins.cpp index b87b904..83ba1c4 100644 --- a/src/Module/builtins.cpp +++ b/src/Module/builtins.cpp @@ -117,7 +117,9 @@ namespace Fig::Builtins return std::make_shared(FString::fromBasicString(line)); }}, {u8"__fvalue_type", - [](const std::vector &args) -> ObjectPtr { return std::make_shared(); }}, + [](const std::vector &args) -> ObjectPtr { + return std::make_shared(args[0]->getTypeInfo().toString()); + }}, {u8"__fvalue_int_parse", [](const std::vector &args) -> ObjectPtr { FString str = args[0]->as(); diff --git a/src/Parser/parser.cpp b/src/Parser/parser.cpp index 8b2025c..cbed366 100644 --- a/src/Parser/parser.cpp +++ b/src/Parser/parser.cpp @@ -9,59 +9,70 @@ namespace Fig { // Operator : pair - const std::unordered_map> Parser::opPrecedence = { - // 算术 - {Ast::Operator::Add, {10, 11}}, - {Ast::Operator::Subtract, {10, 11}}, - {Ast::Operator::Multiply, {20, 21}}, - {Ast::Operator::Divide, {20, 21}}, - {Ast::Operator::Modulo, {20, 21}}, - {Ast::Operator::Power, {30, 29}}, + // 赋值类 - 右结合 + {Ast::Operator::Assign, {20, 10}}, + {Ast::Operator::PlusAssign, {20, 10}}, + {Ast::Operator::MinusAssign, {20, 10}}, + {Ast::Operator::SlashAssign, {20, 10}}, + {Ast::Operator::AsteriskAssign, {20, 10}}, + {Ast::Operator::PercentAssign, {20, 10}}, + {Ast::Operator::CaretAssign, {20, 10}}, - // 逻辑 - {Ast::Operator::And, {5, 6}}, - {Ast::Operator::Or, {4, 5}}, - // {Ast::Operator::Not, {30, 31}}, // 一元 + // 三元条件 - 特殊处理,通常是右结合 + {Ast::Operator::TernaryCond, {30, 20}}, - // 比较 - {Ast::Operator::Equal, {7, 8}}, - {Ast::Operator::NotEqual, {7, 8}}, - {Ast::Operator::Less, {8, 9}}, - {Ast::Operator::LessEqual, {8, 9}}, - {Ast::Operator::Greater, {8, 9}}, - {Ast::Operator::GreaterEqual, {8, 9}}, - {Ast::Operator::Is, {8, 9}}, + // 逻辑或 + {Ast::Operator::Or, {40, 41}}, // leftBP < rightBP,左结合 - // 位运算 - {Ast::Operator::BitAnd, {6, 7}}, - {Ast::Operator::BitOr, {4, 5}}, - {Ast::Operator::BitXor, {5, 6}}, - // {Ast::Operator::BitNot, {30, 31}}, // 一元 - {Ast::Operator::ShiftLeft, {15, 16}}, - {Ast::Operator::ShiftRight, {15, 16}}, + // 逻辑与 + {Ast::Operator::And, {50, 51}}, // 比 Or 高 - {Ast::Operator::Assign, {2, 1}}, // 右结合 - {Ast::Operator::PlusAssign, {2, 1}}, - {Ast::Operator::MinusAssign, {2, 1}}, - {Ast::Operator::SlashAssign, {2, 1}}, - {Ast::Operator::AsteriskAssign, {2, 1}}, - {Ast::Operator::PercentAssign, {2, 1}}, - {Ast::Operator::CaretAssign, {2, 1}}, + // 位或 + {Ast::Operator::BitOr, {60, 61}}, - // 海象运算符 - // {Ast::Operator::Walrus, {2, 1}}, // 右结合 + // 位异或 + {Ast::Operator::BitXor, {70, 71}}, - // // 点运算符 - // {Ast::Operator::Dot, {40, 41}}, - {Ast::Operator::TernaryCond, {3, 2}}, + // 位与 + {Ast::Operator::BitAnd, {80, 81}}, + + // 相等比较 + {Ast::Operator::Equal, {90, 91}}, + {Ast::Operator::NotEqual, {90, 91}}, + + // 关系比较 + {Ast::Operator::Less, {100, 101}}, + {Ast::Operator::LessEqual, {100, 101}}, + {Ast::Operator::Greater, {100, 101}}, + {Ast::Operator::GreaterEqual, {100, 101}}, + {Ast::Operator::Is, {100, 101}}, + + // 位移 + {Ast::Operator::ShiftLeft, {110, 111}}, + {Ast::Operator::ShiftRight, {110, 111}}, + + // 加减 + {Ast::Operator::Add, {120, 121}}, + {Ast::Operator::Subtract, {120, 121}}, + + // 乘除模 + {Ast::Operator::Multiply, {130, 131}}, + {Ast::Operator::Divide, {130, 131}}, + {Ast::Operator::Modulo, {130, 131}}, + + // 幂运算 - 右结合 + {Ast::Operator::Power, {140, 139}}, // leftBP > rightBP }; + // 赋值 < 三元 < 逻辑或 < 逻辑与 < 位运算 < 比较 < 位移 < 加减 < 乘除 < 幂 < 一元 + + // 一元运算符的优先级比所有二元运算符都高 const std::unordered_map Parser::unaryOpPrecedence = { {Ast::Operator::Subtract, 150}, // - - {Ast::Operator::BitAnd, 150}, // & {Ast::Operator::BitNot, 150}, // ~ {Ast::Operator::Not, 150}, // ! + {Ast::Operator::BitAnd, 150}, // &(取地址) }; Ast::VarDef Parser::__parseVarDef(bool isPublic)