feat: 增加repl入口,-r/--repl。 添加计时选项。 -- 我发现一个问题,analyzer没法保存环境。完了。
This commit is contained in:
@@ -75,7 +75,7 @@ namespace Fig
|
|||||||
stream << std::format(" [{}] {}\n", i, proto->constants[i].ToString());
|
stream << std::format(" [{}] {}\n", i, proto->constants[i].ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stream << "--- End Disassembly ---";
|
stream << "--- End Disassembly ---\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
Disassembler::Format Disassembler::GetFormat(OpCode op)
|
Disassembler::Format Disassembler::GetFormat(OpCode op)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*!
|
/*!
|
||||||
@file src/Compiler/ExprCompiler.cpp
|
@file src/Compiler/ExprCompiler.cpp
|
||||||
@brief 表达式编译器实现:引入水位线(Watermark)与零拷贝复用机制
|
@brief 表达式编译器实现:水位线控制Register与零拷贝复用机制
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <Ast/Expr/CallExpr.hpp>
|
#include <Ast/Expr/CallExpr.hpp>
|
||||||
@@ -19,46 +19,69 @@ namespace Fig
|
|||||||
char buffer[128];
|
char buffer[128];
|
||||||
int j = 0;
|
int j = 0;
|
||||||
bool isFloat = false;
|
bool isFloat = false;
|
||||||
|
|
||||||
for (size_t i = 0; i < raw.length() && j < 127; ++i)
|
for (size_t i = 0; i < raw.length() && j < 127; ++i)
|
||||||
{
|
{
|
||||||
char32_t c = raw[i];
|
char32_t c = raw[i];
|
||||||
if (c == '_')
|
if (c == '_')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// 检查开头的无效字符
|
||||||
|
if (j == 0 && (c == '.' || c == 'e' || c == 'E'))
|
||||||
|
return std::unexpected(
|
||||||
|
Error(ErrorType::SyntaxError, "unexpected leading character", "", loc));
|
||||||
|
|
||||||
if (c == '.' || c == 'e' || c == 'E')
|
if (c == '.' || c == 'e' || c == 'E')
|
||||||
isFloat = true;
|
isFloat = true;
|
||||||
buffer[j++] = (char) c;
|
buffer[j++] = (char) c;
|
||||||
}
|
}
|
||||||
buffer[j] = '\0';
|
buffer[j] = '\0';
|
||||||
|
|
||||||
|
// 检查16进制/2进制前缀
|
||||||
|
bool isHexOrBin = false;
|
||||||
|
int base = 10;
|
||||||
|
const char *start = buffer;
|
||||||
|
|
||||||
|
if (j >= 2 && buffer[0] == '0')
|
||||||
|
{
|
||||||
|
if (buffer[1] == 'x' || buffer[1] == 'X')
|
||||||
|
{
|
||||||
|
base = 16;
|
||||||
|
start += 2;
|
||||||
|
isHexOrBin = true;
|
||||||
|
}
|
||||||
|
else if (buffer[1] == 'b' || buffer[1] == 'B')
|
||||||
|
{
|
||||||
|
base = 2;
|
||||||
|
start += 2;
|
||||||
|
isHexOrBin = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isFloat)
|
if (isFloat)
|
||||||
{
|
{
|
||||||
|
// 如果既有浮点标记又是0x开头,可能是16进制浮点
|
||||||
|
auto fmt =
|
||||||
|
(isHexOrBin && base == 16) ? std::chars_format::hex : std::chars_format::general;
|
||||||
|
|
||||||
double dVal;
|
double dVal;
|
||||||
auto [ptr, ec] = std::from_chars(buffer, buffer + j, dVal);
|
auto [ptr, ec] = std::from_chars(start, buffer + j, dVal, fmt);
|
||||||
if (ec != std::errc())
|
|
||||||
return std::unexpected(Error(ErrorType::SyntaxError, "float overflow", "", loc));
|
if (ec != std::errc() || ptr != buffer + j)
|
||||||
|
return std::unexpected(
|
||||||
|
Error(ErrorType::SyntaxError, "invalid float literal", "", loc));
|
||||||
|
|
||||||
return Value::FromDouble(dVal);
|
return Value::FromDouble(dVal);
|
||||||
}
|
}
|
||||||
else
|
else if (isHexOrBin)
|
||||||
{
|
{
|
||||||
int base = 10;
|
// 16进制或2进制整数
|
||||||
const char *start = buffer;
|
|
||||||
if (j > 2 && buffer[0] == '0')
|
|
||||||
{
|
|
||||||
if (buffer[1] == 'x' || buffer[1] == 'X')
|
|
||||||
{
|
|
||||||
base = 16;
|
|
||||||
start += 2;
|
|
||||||
}
|
|
||||||
else if (buffer[1] == 'b' || buffer[1] == 'B')
|
|
||||||
{
|
|
||||||
base = 2;
|
|
||||||
start += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int64_t iVal;
|
int64_t iVal;
|
||||||
auto [ptr, ec] = std::from_chars(start, buffer + j, iVal, base);
|
auto [ptr, ec] = std::from_chars(start, buffer + j, iVal, base);
|
||||||
if (ec != std::errc())
|
|
||||||
return std::unexpected(Error(ErrorType::SyntaxError, "integer overflow", "", loc));
|
if (ec != std::errc() || ptr != buffer + j)
|
||||||
|
return std::unexpected(
|
||||||
|
Error(ErrorType::SyntaxError, "integer overflow or invalid literal", "", loc));
|
||||||
|
|
||||||
if (iVal >= std::numeric_limits<int32_t>::min()
|
if (iVal >= std::numeric_limits<int32_t>::min()
|
||||||
&& iVal <= std::numeric_limits<int32_t>::max())
|
&& iVal <= std::numeric_limits<int32_t>::max())
|
||||||
@@ -70,6 +93,27 @@ namespace Fig
|
|||||||
return Value::FromDouble(static_cast<double>(iVal));
|
return Value::FromDouble(static_cast<double>(iVal));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 10进制数字,可能是整数或浮点数
|
||||||
|
double dVal;
|
||||||
|
auto [ptr, ec] = std::from_chars(start, buffer + j, dVal, std::chars_format::general);
|
||||||
|
|
||||||
|
if (ec != std::errc() || ptr != buffer + j)
|
||||||
|
return std::unexpected(
|
||||||
|
Error(ErrorType::SyntaxError, "invalid number literal", "", loc));
|
||||||
|
|
||||||
|
// 检查是否是整数(没有小数部分且不超出int32范围)
|
||||||
|
if (dVal == std::floor(dVal) && dVal >= std::numeric_limits<int32_t>::min()
|
||||||
|
&& dVal <= std::numeric_limits<int32_t>::max())
|
||||||
|
{
|
||||||
|
return Value::FromInt(static_cast<int32_t>(dVal));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Value::FromDouble(dVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Register, Error> Compiler::compileExpr(Expr *expr, Register target)
|
Result<Register, Error> Compiler::compileExpr(Expr *expr, Register target)
|
||||||
@@ -287,30 +331,61 @@ namespace Fig
|
|||||||
OpCode op;
|
OpCode op;
|
||||||
switch (in->op)
|
switch (in->op)
|
||||||
{
|
{
|
||||||
case BinaryOperator::Add: op = isInt ? OpCode::IntFastAdd : OpCode::Add; break;
|
case BinaryOperator::Add: {
|
||||||
case BinaryOperator::Subtract:
|
op = (isInt ? (OpCode::IntFastAdd) : (OpCode::Add));
|
||||||
op = isInt ? OpCode::IntFastSub : OpCode::Sub;
|
|
||||||
break;
|
break;
|
||||||
case BinaryOperator::Multiply:
|
}
|
||||||
op = isInt ? OpCode::IntFastMul : OpCode::Mul;
|
case BinaryOperator::Subtract: {
|
||||||
|
op = (isInt ? (OpCode::IntFastSub) : (OpCode::Sub));
|
||||||
break;
|
break;
|
||||||
case BinaryOperator::Divide:
|
}
|
||||||
op = isInt ? OpCode::IntFastDiv : OpCode::Div;
|
case BinaryOperator::Multiply: {
|
||||||
|
op = (isInt ? (OpCode::IntFastMul) : (OpCode::Mul));
|
||||||
break;
|
break;
|
||||||
case BinaryOperator::Modulo: op = OpCode::Mod; break;
|
}
|
||||||
case BinaryOperator::BitXor: op = OpCode::BitXor; break;
|
case BinaryOperator::Divide: {
|
||||||
case BinaryOperator::Equal: op = OpCode::Equal; break;
|
op = (isInt ? (OpCode::IntFastDiv) : (OpCode::Div));
|
||||||
case BinaryOperator::NotEqual: op = OpCode::NotEqual; break;
|
break;
|
||||||
case BinaryOperator::Greater: op = OpCode::Greater; break;
|
}
|
||||||
case BinaryOperator::Less: op = OpCode::Less; break;
|
case BinaryOperator::Modulo: {
|
||||||
case BinaryOperator::GreaterEqual: op = OpCode::GreaterEqual; break;
|
op = OpCode::Mod;
|
||||||
case BinaryOperator::LessEqual: op = OpCode::LessEqual; break;
|
break;
|
||||||
default:
|
}
|
||||||
|
case BinaryOperator::BitXor: {
|
||||||
|
op = OpCode::BitXor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BinaryOperator::Equal: {
|
||||||
|
op = OpCode::Equal;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BinaryOperator::NotEqual: {
|
||||||
|
op = OpCode::NotEqual;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BinaryOperator::Greater: {
|
||||||
|
op = OpCode::Greater;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BinaryOperator::Less: {
|
||||||
|
op = OpCode::Less;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BinaryOperator::GreaterEqual: {
|
||||||
|
op = OpCode::GreaterEqual;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BinaryOperator::LessEqual: {
|
||||||
|
op = OpCode::LessEqual;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
return std::unexpected(Error(
|
return std::unexpected(Error(
|
||||||
ErrorType::InternalError,
|
ErrorType::InternalError,
|
||||||
"unsupported binary operator",
|
"unsupported binary operator",
|
||||||
"",
|
"",
|
||||||
in->location));
|
in->location));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 释放左右操作数产生的临时寄存器
|
// 释放左右操作数产生的临时寄存器
|
||||||
|
|||||||
@@ -38,15 +38,18 @@ namespace Fig
|
|||||||
|
|
||||||
void PrintInfo()
|
void PrintInfo()
|
||||||
{
|
{
|
||||||
out << std::format("Fig {}, copyright (c) 2025-2026 PuqiAR, under the {} License\n",
|
out << std::format(
|
||||||
|
"Fig {}, copyright (c) 2025-2026 PuqiAR, under the {} License\n",
|
||||||
Core::VERSION,
|
Core::VERSION,
|
||||||
Core::LICENSE);
|
Core::LICENSE);
|
||||||
out << std::format("Build time: {} [{} x{} on {}]\n",
|
out << std::format(
|
||||||
|
"Build time: {} [{} x{} on {}]\n",
|
||||||
Core::COMPILE_TIME,
|
Core::COMPILE_TIME,
|
||||||
Core::COMPILER,
|
Core::COMPILER,
|
||||||
Core::ARCH,
|
Core::ARCH,
|
||||||
Core::PLATFORM);
|
Core::PLATFORM);
|
||||||
out << "Type '#exit' to exit, '#clear' to clear the the screen, '#license' to see the full license, '#logo' to see a GREAT logo\n";
|
out << "Type '#exit' to exit, '#clear' to clear the the screen, '#license' to see the full license, '#logo' to see a GREAT logo\n";
|
||||||
|
out << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClearConsole()
|
void ClearConsole()
|
||||||
@@ -146,17 +149,58 @@ namespace Fig
|
|||||||
++rline;
|
++rline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// void PrintError(const Error &error, const String &source)
|
||||||
|
// {
|
||||||
|
// err << "Oops! An error occurred!";
|
||||||
|
// err << "🔥 " << 'E' << static_cast<int>(error.type) << ": " << error.message << '\n';
|
||||||
|
// err << "Line " << rline << ", `" << source << "`\n";
|
||||||
|
// err << "Suggestion: " << error.suggestion << '\n';
|
||||||
|
// err << std::format(
|
||||||
|
// "Thrower: {} ({}:{}:{})\n",
|
||||||
|
// error.thrower_loc.function_name(),
|
||||||
|
// error.thrower_loc.file_name(),
|
||||||
|
// error.thrower_loc.line(),
|
||||||
|
// error.thrower_loc.column());
|
||||||
|
// }
|
||||||
|
|
||||||
void PrintError(const Error &error, const String &source)
|
void PrintError(const Error &error, const String &source)
|
||||||
{
|
{
|
||||||
err << "Oops! An error occurred!";
|
static constexpr const char *MinorColor = "\033[38;2;138;227;198m";
|
||||||
err << "🔥 " << 'E' << static_cast<int>(error.type) << ": " << error.message << '\n';
|
static constexpr const char *MediumColor = "\033[38;2;255;199;95m";
|
||||||
err << "Line " << rline << ", `" << source << "`\n";
|
static constexpr const char *CriticalColor = "\033[38;2;255;107;107m";
|
||||||
err << "Suggestion: " << error.suggestion << '\n';
|
|
||||||
err << std::format("Thrower: {} ({}:{}:{})\n",
|
namespace TC = TerminalColors;
|
||||||
error.thrower_loc.function_name(),
|
std::ostream &err = CoreIO::GetStdErr();
|
||||||
error.thrower_loc.file_name(),
|
|
||||||
error.thrower_loc.line(),
|
uint8_t level = ErrorLevel(error.type);
|
||||||
error.thrower_loc.column());
|
// const char *level_name = (level == 1 ? "Minor" : (level == 2 ? "Medium" :
|
||||||
|
// "Critical"));
|
||||||
|
const char *const &level_color =
|
||||||
|
(level == 1 ? MinorColor : (level == 2 ? MediumColor : CriticalColor));
|
||||||
|
|
||||||
|
err << "\n";
|
||||||
|
err << "🔥 "
|
||||||
|
<< level_color
|
||||||
|
//<< '(' << level_name << ')'
|
||||||
|
<< '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 << " │" << '\n' << " │" << TC::Reset << '\n';
|
||||||
|
err << TC::DarkGray << " └─ " << TC::Reset;
|
||||||
|
err << source << "\n";
|
||||||
|
|
||||||
|
err << "\n";
|
||||||
|
err << "❓ " << TC::DarkGray << "Thrower: " << error.thrower_loc.function_name() << " ("
|
||||||
|
<< error.thrower_loc.file_name() << ":" << error.thrower_loc.line() << ")"
|
||||||
|
<< TC::Reset << "\n";
|
||||||
|
err << "💡 " << TC::Blue << "Suggestion: " << error.suggestion << TC::Reset;
|
||||||
|
err << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Start() // exit code: unsigned int
|
unsigned int Start() // exit code: unsigned int
|
||||||
@@ -208,7 +252,7 @@ namespace Fig
|
|||||||
|
|
||||||
String source(buf);
|
String source(buf);
|
||||||
|
|
||||||
Lexer lexer(buf, fileName);
|
Lexer lexer(buf, fileName);
|
||||||
|
|
||||||
Diagnostics diagnostics;
|
Diagnostics diagnostics;
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include <VM/Entry.hpp>
|
#include <VM/Entry.hpp>
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
#include <Core/Core.hpp>
|
#include <Core/Core.hpp>
|
||||||
@@ -16,16 +17,50 @@
|
|||||||
#include <Compiler/Compiler.hpp>
|
#include <Compiler/Compiler.hpp>
|
||||||
#include <Lexer/Lexer.hpp>
|
#include <Lexer/Lexer.hpp>
|
||||||
#include <Parser/Parser.hpp>
|
#include <Parser/Parser.hpp>
|
||||||
|
#include <Repl/Repl.hpp>
|
||||||
#include <Sema/Analyzer.hpp>
|
#include <Sema/Analyzer.hpp>
|
||||||
#include <VM/VM.hpp>
|
#include <VM/VM.hpp>
|
||||||
|
|
||||||
|
|
||||||
namespace Fig::Entry
|
namespace Fig::Entry
|
||||||
{
|
{
|
||||||
void RunFromPath(const String &path, const Config &conf)
|
void RunFromPath(const String &path, const Config &conf)
|
||||||
{
|
{
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
using clock = std::chrono::steady_clock;
|
||||||
|
|
||||||
|
auto format_print_time = [](std::chrono::nanoseconds nsecs) {
|
||||||
|
auto &out = CoreIO::GetStdOut();
|
||||||
|
auto count = nsecs.count();
|
||||||
|
|
||||||
|
auto old_flags = out.flags();
|
||||||
|
auto old_precision = out.precision();
|
||||||
|
|
||||||
|
if (count < 1'000)
|
||||||
|
{
|
||||||
|
// < 1μs 纳秒
|
||||||
|
out << count << "ns";
|
||||||
|
}
|
||||||
|
else if (count < 1'000'000)
|
||||||
|
{
|
||||||
|
// 1μs ~ 1ms 微秒 保留 2 位小数
|
||||||
|
out << std::fixed << std::setprecision(2) << (count / 1'000.0) << "μs";
|
||||||
|
}
|
||||||
|
else if (count < 1'000'000'000)
|
||||||
|
{
|
||||||
|
// 1ms ~ 1s 毫秒 保留 2 位小数
|
||||||
|
out << std::fixed << std::setprecision(2) << (count / 1'000'000.0) << "ms";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// >= 1s 秒 保留 3 位小数
|
||||||
|
out << std::fixed << std::setprecision(3) << (count / 1'000'000'000.0) << "s";
|
||||||
|
}
|
||||||
|
|
||||||
|
out.flags(old_flags);
|
||||||
|
out.precision(old_precision);
|
||||||
|
};
|
||||||
|
|
||||||
fs::path _fspath(path.toStdString());
|
fs::path _fspath(path.toStdString());
|
||||||
|
|
||||||
if (!fs::exists(_fspath))
|
if (!fs::exists(_fspath))
|
||||||
@@ -53,22 +88,29 @@ namespace Fig::Entry
|
|||||||
|
|
||||||
const String &source = manager.GetSource();
|
const String &source = manager.GetSource();
|
||||||
|
|
||||||
Lexer lexer(source, fileName);
|
Lexer lexer(source, fileName);
|
||||||
|
|
||||||
Diagnostics diagnostics;
|
Diagnostics diagnostics;
|
||||||
|
|
||||||
Parser parser(lexer, manager, fileName, diagnostics);
|
Parser parser(lexer, manager, fileName, diagnostics);
|
||||||
|
|
||||||
|
auto parse_start = clock::now();
|
||||||
auto parse_result = parser.Parse();
|
auto parse_result = parser.Parse();
|
||||||
|
auto parse_end = clock::now();
|
||||||
|
|
||||||
if (!parse_result)
|
if (!parse_result)
|
||||||
{
|
{
|
||||||
ReportError(parse_result.error(), manager);
|
ReportError(parse_result.error(), manager);
|
||||||
std::exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Program *program = *parse_result;
|
Program *program = *parse_result;
|
||||||
|
|
||||||
Analyzer analyer(manager);
|
Analyzer analyer(manager);
|
||||||
auto analyze_result = analyer.Analyze(program);
|
|
||||||
|
auto analyze_start = clock::now();
|
||||||
|
auto analyze_result = analyer.Analyze(program);
|
||||||
|
auto analyze_end = clock::now();
|
||||||
|
|
||||||
if (!analyze_result)
|
if (!analyze_result)
|
||||||
{
|
{
|
||||||
@@ -76,9 +118,12 @@ namespace Fig::Entry
|
|||||||
std::exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Compiler compiler(manager, diagnostics);
|
Compiler compiler(manager, diagnostics);
|
||||||
|
|
||||||
|
auto compile_start = clock::now();
|
||||||
auto compile_result = compiler.Compile(program);
|
auto compile_result = compiler.Compile(program);
|
||||||
|
auto compile_end = clock::now();
|
||||||
|
|
||||||
diagnostics.EmitAll(manager);
|
diagnostics.EmitAll(manager);
|
||||||
|
|
||||||
if (!compile_result)
|
if (!compile_result)
|
||||||
@@ -97,7 +142,10 @@ namespace Fig::Entry
|
|||||||
|
|
||||||
VM vm;
|
VM vm;
|
||||||
|
|
||||||
|
auto execute_start = clock::now();
|
||||||
auto execute_result = vm.Execute(compiledModule);
|
auto execute_result = vm.Execute(compiledModule);
|
||||||
|
auto execute_end = clock::now();
|
||||||
|
|
||||||
if (!execute_result)
|
if (!execute_result)
|
||||||
{
|
{
|
||||||
ReportError(execute_result.error(), manager);
|
ReportError(execute_result.error(), manager);
|
||||||
@@ -109,6 +157,43 @@ namespace Fig::Entry
|
|||||||
vm.PrintRegisters();
|
vm.PrintRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (conf.time)
|
||||||
|
{
|
||||||
|
auto parse_time = parse_end - parse_start;
|
||||||
|
CoreIO::GetStdOut() << "Parse: ";
|
||||||
|
format_print_time(parse_time);
|
||||||
|
CoreIO::GetStdOut() << " | ";
|
||||||
|
|
||||||
|
auto analyze_time = analyze_end - analyze_start;
|
||||||
|
CoreIO::GetStdOut() << "Analyze: ";
|
||||||
|
format_print_time(analyze_time);
|
||||||
|
CoreIO::GetStdOut() << " | ";
|
||||||
|
|
||||||
|
auto compile_time = compile_end - compile_start;
|
||||||
|
CoreIO::GetStdOut() << "Compile: ";
|
||||||
|
format_print_time(compile_time);
|
||||||
|
CoreIO::GetStdOut() << " | ";
|
||||||
|
|
||||||
|
auto execute_time = execute_end - execute_start;
|
||||||
|
CoreIO::GetStdOut() << "Execute: ";
|
||||||
|
format_print_time(execute_time);
|
||||||
|
CoreIO::GetStdOut() << " | ";
|
||||||
|
|
||||||
|
auto total = parse_time + analyze_time + compile_time + execute_time;
|
||||||
|
CoreIO::GetStdOut() << "Total: ";
|
||||||
|
format_print_time(total);
|
||||||
|
CoreIO::GetStdOut() << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
delete compiledModule;
|
delete compiledModule;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::uint32_t RunRepl()
|
||||||
|
{
|
||||||
|
Repl repl(CoreIO::GetStdCin(), CoreIO::GetStdOut(), CoreIO::GetStdErr());
|
||||||
|
std::uint32_t result = repl.Start();
|
||||||
|
|
||||||
|
CoreIO::GetStdOut() << "Repl exited with code " << result << '\n';
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}; // namespace Fig::Entry
|
}; // namespace Fig::Entry
|
||||||
@@ -18,6 +18,9 @@ namespace Fig::Entry
|
|||||||
} mode;
|
} mode;
|
||||||
bool dump;
|
bool dump;
|
||||||
bool pregs;
|
bool pregs;
|
||||||
|
bool time;
|
||||||
};
|
};
|
||||||
|
|
||||||
void RunFromPath(const String &, const Config &conf);
|
void RunFromPath(const String &, const Config &conf);
|
||||||
|
std::uint32_t RunRepl();
|
||||||
};
|
};
|
||||||
@@ -329,7 +329,7 @@ namespace Fig
|
|||||||
Op::iAsBx(OpCode::Exit_MaxRecursionDepthExceeded, 0, 0);
|
Op::iAsBx(OpCode::Exit_MaxRecursionDepthExceeded, 0, 0);
|
||||||
return &POISON_MAX_RECURSION_DEPTH_EXCEED_INST;
|
return &POISON_MAX_RECURSION_DEPTH_EXCEED_INST;
|
||||||
}
|
}
|
||||||
|
[[likely]]
|
||||||
*currentFrame = CallFrame{nullptr, proto, proto->code.data(), base};
|
*currentFrame = CallFrame{nullptr, proto, proto->code.data(), base};
|
||||||
return currentFrame->ip;
|
return currentFrame->ip;
|
||||||
}
|
}
|
||||||
@@ -343,7 +343,7 @@ namespace Fig
|
|||||||
Op::iAsBx(OpCode::Exit_MaxRecursionDepthExceeded, 0, 0);
|
Op::iAsBx(OpCode::Exit_MaxRecursionDepthExceeded, 0, 0);
|
||||||
return &POISON_MAX_RECURSION_DEPTH_EXCEED_INST;
|
return &POISON_MAX_RECURSION_DEPTH_EXCEED_INST;
|
||||||
}
|
}
|
||||||
|
[[likely]]
|
||||||
*currentFrame = CallFrame{closure, closure->proto, closure->proto->code.data(), base};
|
*currentFrame = CallFrame{closure, closure->proto, closure->proto->code.data(), base};
|
||||||
return currentFrame->ip;
|
return currentFrame->ip;
|
||||||
}
|
}
|
||||||
|
|||||||
11
src/main.cpp
11
src/main.cpp
@@ -19,11 +19,13 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
ArgParser::ArgumentParser argparser("Fig", "Fig Toolchain");
|
ArgParser::ArgumentParser argparser("Fig", "Fig Toolchain");
|
||||||
|
|
||||||
|
argparser.AddFlag('r', "repl");
|
||||||
argparser.AddFlag('h', "help").Help("Print the help message");
|
argparser.AddFlag('h', "help").Help("Print the help message");
|
||||||
argparser.AddFlag('v', "version").Help("Show toolchain version");
|
argparser.AddFlag('v', "version").Help("Show toolchain version");
|
||||||
argparser.AddFlag("license").Help("Print the license text");
|
argparser.AddFlag("license").Help("Print the license text");
|
||||||
argparser.AddFlag("dump").Help("Dump the bytecode");
|
argparser.AddFlag("dump").Help("Dump the bytecode");
|
||||||
argparser.AddFlag("pregs").Help("Print vm non-null registers");
|
argparser.AddFlag("pregs").Help("Print vm non-null registers");
|
||||||
|
argparser.AddFlag("time").Help("Print the execution time");
|
||||||
|
|
||||||
auto res = argparser.Parse(argc, argv);
|
auto res = argparser.Parse(argc, argv);
|
||||||
if (!res)
|
if (!res)
|
||||||
@@ -34,11 +36,13 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
auto &args = *res;
|
auto &args = *res;
|
||||||
|
|
||||||
|
bool runRepl = args.HasFlag("repl");
|
||||||
bool showHelp = args.HasFlag("help");
|
bool showHelp = args.HasFlag("help");
|
||||||
bool showVersion = args.HasFlag("version");
|
bool showVersion = args.HasFlag("version");
|
||||||
bool showLicense = args.HasFlag("license");
|
bool showLicense = args.HasFlag("license");
|
||||||
bool dump = args.HasFlag("dump");
|
bool dump = args.HasFlag("dump");
|
||||||
bool pregs = args.HasFlag("pregs");
|
bool pregs = args.HasFlag("pregs");
|
||||||
|
bool time = args.HasFlag("time");
|
||||||
|
|
||||||
if (showHelp)
|
if (showHelp)
|
||||||
{
|
{
|
||||||
@@ -72,6 +76,11 @@ int main(int argc, char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (runRepl)
|
||||||
|
{
|
||||||
|
return Entry::RunRepl();
|
||||||
|
}
|
||||||
|
|
||||||
if (posSize > 1)
|
if (posSize > 1)
|
||||||
{
|
{
|
||||||
err << "Error: Too more positionals, expect 1. Use Fig [Fig source code file (.fig)]\n";
|
err << "Error: Too more positionals, expect 1. Use Fig [Fig source code file (.fig)]\n";
|
||||||
@@ -83,7 +92,7 @@ int main(int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry::Config config{.mode = Entry::Config::Normal, .dump = dump, .pregs = pregs};
|
Entry::Config config{.mode = Entry::Config::Normal, .dump = dump, .pregs = pregs, .time = time};
|
||||||
|
|
||||||
const String &path = positionals.front();
|
const String &path = positionals.front();
|
||||||
Entry::RunFromPath(path, config);
|
Entry::RunFromPath(path, config);
|
||||||
|
|||||||
Reference in New Issue
Block a user