这是一条 msg. ( 正文:error log修改。新增std.tester。parser precedence重写
This commit is contained in:
@@ -110,21 +110,31 @@ namespace Fig
|
|||||||
coloredPrint(TC::LightRed, "✖ ");
|
coloredPrint(TC::LightRed, "✖ ");
|
||||||
coloredPrint(TC::LightRed, std::format("{}: {}\n", err.getErrorType().toBasicString(), FString(err.getMessage()).toBasicString()));
|
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()));
|
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"<No Source>");
|
|
||||||
coloredPrint(TC::LightBlue, std::format(" {}\n", lineContent.toBasicString()));
|
FString lineContent;
|
||||||
FString pointerLine;
|
FString pointerLine;
|
||||||
for (size_t i = 1; i < err.getColumn(); ++i)
|
|
||||||
|
if (fileName != u8"<stdin>")
|
||||||
{
|
{
|
||||||
if (lineContent[i - 1] == U'\t')
|
lineContent = ((int64_t(err.getLine()) - int64_t(1)) >= 0 ? sourceLines[err.getLine() - 1] : u8"<No Source>");
|
||||||
|
FString pointerLine;
|
||||||
|
for (size_t i = 1; i < err.getColumn(); ++i)
|
||||||
{
|
{
|
||||||
pointerLine += U'\t';
|
if (lineContent[i - 1] == U'\t') { pointerLine += U'\t'; }
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
pointerLine += U' ';
|
||||||
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::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()));
|
coloredPrint(TC::DarkGray, std::format("🔧 in function '{}' ({}:{})\n", err.src_loc.function_name(), err.src_loc.file_name(), err.src_loc.line()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -429,7 +429,7 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
if (is<ValueType::NullClass>()) return FString(u8"null");
|
if (is<ValueType::NullClass>()) return FString(u8"null");
|
||||||
if (is<ValueType::IntClass>()) return FString(std::to_string(as<ValueType::IntClass>()));
|
if (is<ValueType::IntClass>()) return FString(std::to_string(as<ValueType::IntClass>()));
|
||||||
if (is<ValueType::DoubleClass>()) return FString(std::format("{:g}", as<ValueType::DoubleClass>()));
|
if (is<ValueType::DoubleClass>()) return FString(std::format("{}", as<ValueType::DoubleClass>()));
|
||||||
if (is<ValueType::StringClass>()) return FString(u8"\"" + as<ValueType::StringClass>() + u8"\"");
|
if (is<ValueType::StringClass>()) return FString(u8"\"" + as<ValueType::StringClass>() + u8"\"");
|
||||||
if (is<ValueType::BoolClass>()) return as<ValueType::BoolClass>() ? FString(u8"true") : FString(u8"false");
|
if (is<ValueType::BoolClass>()) return as<ValueType::BoolClass>() ? FString(u8"true") : FString(u8"false");
|
||||||
if (is<Function>())
|
if (is<Function>())
|
||||||
|
|||||||
@@ -6,3 +6,4 @@
|
|||||||
import io; // link std.io
|
import io; // link std.io
|
||||||
import value; // link std.type
|
import value; // link std.type
|
||||||
import math; // link std.math
|
import math; // link std.math
|
||||||
|
import tester; // link std.tester
|
||||||
86
src/Module/Library/std/tester/tester.fig
Normal file
86
src/Module/Library/std/tester/tester.fig
Normal file
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -117,7 +117,9 @@ namespace Fig::Builtins
|
|||||||
return std::make_shared<Object>(FString::fromBasicString(line));
|
return std::make_shared<Object>(FString::fromBasicString(line));
|
||||||
}},
|
}},
|
||||||
{u8"__fvalue_type",
|
{u8"__fvalue_type",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { return std::make_shared<Object>(); }},
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
|
return std::make_shared<Object>(args[0]->getTypeInfo().toString());
|
||||||
|
}},
|
||||||
{u8"__fvalue_int_parse",
|
{u8"__fvalue_int_parse",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
FString str = args[0]->as<ValueType::StringClass>();
|
FString str = args[0]->as<ValueType::StringClass>();
|
||||||
|
|||||||
@@ -9,59 +9,70 @@
|
|||||||
namespace Fig
|
namespace Fig
|
||||||
{
|
{
|
||||||
// Operator : pair<LeftBindingPower, RightBindingPower>
|
// Operator : pair<LeftBindingPower, RightBindingPower>
|
||||||
|
|
||||||
const std::unordered_map<Ast::Operator, std::pair<Parser::Precedence, Parser::Precedence>> Parser::opPrecedence = {
|
const std::unordered_map<Ast::Operator, std::pair<Parser::Precedence, Parser::Precedence>> Parser::opPrecedence = {
|
||||||
// 算术
|
// 赋值类 - 右结合
|
||||||
{Ast::Operator::Add, {10, 11}},
|
{Ast::Operator::Assign, {20, 10}},
|
||||||
{Ast::Operator::Subtract, {10, 11}},
|
{Ast::Operator::PlusAssign, {20, 10}},
|
||||||
{Ast::Operator::Multiply, {20, 21}},
|
{Ast::Operator::MinusAssign, {20, 10}},
|
||||||
{Ast::Operator::Divide, {20, 21}},
|
{Ast::Operator::SlashAssign, {20, 10}},
|
||||||
{Ast::Operator::Modulo, {20, 21}},
|
{Ast::Operator::AsteriskAssign, {20, 10}},
|
||||||
{Ast::Operator::Power, {30, 29}},
|
{Ast::Operator::PercentAssign, {20, 10}},
|
||||||
|
{Ast::Operator::CaretAssign, {20, 10}},
|
||||||
|
|
||||||
// 逻辑
|
// 三元条件 - 特殊处理,通常是右结合
|
||||||
{Ast::Operator::And, {5, 6}},
|
{Ast::Operator::TernaryCond, {30, 20}},
|
||||||
{Ast::Operator::Or, {4, 5}},
|
|
||||||
// {Ast::Operator::Not, {30, 31}}, // 一元
|
|
||||||
|
|
||||||
// 比较
|
// 逻辑或
|
||||||
{Ast::Operator::Equal, {7, 8}},
|
{Ast::Operator::Or, {40, 41}}, // leftBP < rightBP,左结合
|
||||||
{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::BitAnd, {6, 7}},
|
{Ast::Operator::And, {50, 51}}, // 比 Or 高
|
||||||
{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::Assign, {2, 1}}, // 右结合
|
// 位或
|
||||||
{Ast::Operator::PlusAssign, {2, 1}},
|
{Ast::Operator::BitOr, {60, 61}},
|
||||||
{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::Walrus, {2, 1}}, // 右结合
|
{Ast::Operator::BitXor, {70, 71}},
|
||||||
|
|
||||||
// // 点运算符
|
// 位与
|
||||||
// {Ast::Operator::Dot, {40, 41}},
|
{Ast::Operator::BitAnd, {80, 81}},
|
||||||
{Ast::Operator::TernaryCond, {3, 2}},
|
|
||||||
|
// 相等比较
|
||||||
|
{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<Ast::Operator, Parser::Precedence> Parser::unaryOpPrecedence = {
|
const std::unordered_map<Ast::Operator, Parser::Precedence> Parser::unaryOpPrecedence = {
|
||||||
{Ast::Operator::Subtract, 150}, // -
|
{Ast::Operator::Subtract, 150}, // -
|
||||||
{Ast::Operator::BitAnd, 150}, // &
|
|
||||||
{Ast::Operator::BitNot, 150}, // ~
|
{Ast::Operator::BitNot, 150}, // ~
|
||||||
{Ast::Operator::Not, 150}, // !
|
{Ast::Operator::Not, 150}, // !
|
||||||
|
{Ast::Operator::BitAnd, 150}, // &(取地址)
|
||||||
};
|
};
|
||||||
|
|
||||||
Ast::VarDef Parser::__parseVarDef(bool isPublic)
|
Ast::VarDef Parser::__parseVarDef(bool isPublic)
|
||||||
|
|||||||
Reference in New Issue
Block a user