feat: 在解析器中实现 Lambda 和 new 表达式

- 增加了对 Lambda 表达式的初步解析支持,包括参数处理和返回类型。Lambda闭包尚未支持。
- 引入了用于对象初始化的新的表达式,支持可选的命名参数。
- 改进了表达式语法错误的错误报告。
- 更新了解析器和分析器以处理新的表达式类型并验证其语义。
- 修改了现有测试以涵盖新功能并确保其正确性。
- 改进了各种解析和语义错误的诊断。
This commit is contained in:
2026-04-12 10:07:51 +08:00
parent 570a87c3cd
commit fafa2b4946
24 changed files with 925 additions and 140 deletions

View File

@@ -17,7 +17,8 @@ namespace Fig
ost << color << msg << TerminalColors::Reset;
}
void ColoredPrint(const char *color, const std::string &msg, std::ostream &ost = CoreIO::GetStdErr())
void
ColoredPrint(const char *color, const std::string &msg, std::ostream &ost = CoreIO::GetStdErr())
{
ost << color << msg << TerminalColors::Reset;
}
@@ -30,7 +31,10 @@ namespace Fig
std::string MultipleStr(const char *c, size_t n)
{
std::string buf;
for (size_t i = 0; i < n; ++i) { buf += c; }
for (size_t i = 0; i < n; ++i)
{
buf += c;
}
return buf;
}
@@ -40,6 +44,7 @@ namespace Fig
switch (type)
{
case UnusedSymbol: return "UnusedSymbol";
case UnnecessarySemicolon: return "UnnecessarySemicolon";
case MayBeNull: return "MaybeNull";
@@ -61,7 +66,8 @@ namespace Fig
case TooManyConstants: return "TooManyConstants";
case RegisterOverflow: return "RegisterOverflow";
case InternalError: return "InternalError";
case InternalError:
return "InternalError";
// default: return "Some one forgot to add case to `ErrorTypeToString`";
}
return "UnknownError";
@@ -69,10 +75,10 @@ namespace Fig
void PrintSystemInfos()
{
std::ostream &err = CoreIO::GetStdErr();
std::ostream &err = CoreIO::GetStdErr();
std::stringstream build_info;
build_info << "\r🌘 Fig v" << Core::VERSION << " on " << Core::PLATFORM << ' ' << Core::ARCH << '['
<< Core::COMPILER << ']' << '\n'
build_info << "\r🌘 Fig v" << Core::VERSION << " on " << Core::PLATFORM << ' ' << Core::ARCH
<< '[' << Core::COMPILER << ']' << '\n'
<< " Build Time: " << Core::COMPILE_TIME;
const std::string &build_info_str = build_info.str();
@@ -83,35 +89,43 @@ namespace Fig
void PrintErrorInfo(const Error &error, const SourceManager &srcManager)
{
static constexpr const char *MinorColor = "\033[38;2;138;227;198m";
static constexpr const char *MediumColor = "\033[38;2;255;199;95m";
static constexpr const char *MinorColor = "\033[38;2;138;227;198m";
static constexpr const char *MediumColor = "\033[38;2;255;199;95m";
static constexpr const char *CriticalColor = "\033[38;2;255;107;107m";
namespace TC = TerminalColors;
namespace TC = TerminalColors;
std::ostream &err = CoreIO::GetStdErr();
uint8_t level = ErrorLevel(error.type);
// const char *level_name = (level == 1 ? "Minor" : (level == 2 ? "Medium" : "Critical"));
const char *level_color = (level == 1 ? MinorColor : (level == 2 ? MediumColor : CriticalColor));
const char *level_color =
(level == 1 ? MinorColor : (level == 2 ? MediumColor : CriticalColor));
err << "🔥 "
<< level_color
//<< '(' << level_name << ')'
<< 'E' << static_cast<int>(error.type) << TC::Reset << ": " << level_color << ErrorTypeToString(error.type)
<< TC::Reset << '\n';
<< 'E' << static_cast<int>(error.type) << TC::Reset << ": " << level_color
<< ErrorTypeToString(error.type) << TC::Reset << '\n';
const SourceLocation &location = error.location;
err << TC::DarkGray << " ┌─> Fn " << TC::Cyan << '\'' << location.packageName << '.' << location.functionName
<< '\'' << " " << location.fileName << " (" << TC::DarkGray << location.sp.line << ":" << location.sp.column
<< TC::Cyan << ')' << TC::Reset << '\n';
err << TC::DarkGray << " ┌─> Fn " << TC::Cyan << '\'' << location.packageName << '.'
<< location.functionName << '\'' << " " << location.fileName << " (" << TC::DarkGray
<< location.sp.line << ":" << location.sp.column << TC::Cyan << ')' << TC::Reset
<< '\n';
err << TC::DarkGray << "" << '\n' << "" << TC::Reset << '\n';
// 尝试打印上3行 下2行
int64_t line_start = location.sp.line - 3, line_end = location.sp.line + 2;
while (!srcManager.HasLine(line_end)) { --line_end; }
while (!srcManager.HasLine(line_start)) { ++line_start; }
while (!srcManager.HasLine(line_end))
{
--line_end;
}
while (!srcManager.HasLine(line_start))
{
++line_start;
}
const auto &getLineNumWidth = [](size_t l) {
unsigned int cnt = 0;
@@ -127,30 +141,39 @@ namespace Fig
{
unsigned int offset = 2 + 2 + 1;
// ' └─ '
if (i == location.sp.line) { err << TC::DarkGray << " └─ " << TC::Reset; }
else if (i < location.sp.line) { err << TC::DarkGray << "" << TC::Reset; }
if (i == location.sp.line)
{
err << TC::DarkGray << " └─ " << TC::Reset;
}
else if (i < location.sp.line)
{
err << TC::DarkGray << "" << TC::Reset;
}
else
{
err << MultipleStr(" ", offset);
}
unsigned int cur_line_number_width = getLineNumWidth(i);
err << MultipleStr(" ", max_line_number_width - cur_line_number_width) << TC::Yellow << i << TC::Reset;
err << MultipleStr(" ", max_line_number_width - cur_line_number_width) << TC::Yellow
<< i << TC::Reset;
err << "" << srcManager.GetLine(i) << '\n';
if (i == location.sp.line)
{
unsigned int error_col_offset = offset + 1 + max_line_number_width + 2;
err << MultipleStr(" ", error_col_offset) << MultipleStr(" ", location.sp.column - 1) << TC::LightGreen
err << MultipleStr(" ", error_col_offset)
<< MultipleStr(" ", location.sp.column - 1) << TC::LightGreen
<< MultipleStr("^", location.sp.tok_length) << TC::Reset << '\n';
err << MultipleStr(" ", error_col_offset)
<< MultipleStr(" ", location.sp.column - 1 + location.sp.tok_length / 2) << "╰─ " << level_color
<< error.message << TC::Reset << "\n\n";
<< MultipleStr(" ", location.sp.column - 1 + location.sp.tok_length / 2)
<< "╰─ " << level_color << error.message << TC::Reset << "\n\n";
}
}
err << "\n";
err << "" << TC::DarkGray << "Thrower: " << error.thrower_loc.function_name() << " ("
<< error.thrower_loc.file_name() << ":" << error.thrower_loc.line() << ")" << TC::Reset << "\n";
<< error.thrower_loc.file_name() << ":" << error.thrower_loc.line() << ")" << TC::Reset
<< "\n";
err << "💡 " << TC::Blue << "Suggestion: " << error.suggestion << TC::Reset;
err << '\n';
}
@@ -158,7 +181,7 @@ namespace Fig
void ReportError(const Error &error, const SourceManager &srcManager)
{
assert(srcManager.read && "ReportError: srcManager doesn't read source");
assert(srcManager.HasLine(error.location.sp.line));
// assert(srcManager.HasLine(error.location.sp.line));
PrintSystemInfos();
PrintErrorInfo(error, srcManager);