forked from PuqiAR/Fig-TreeWalker
[Fix] 修复科学表达式数字解析的问题(Lexer引起) 由 Satklomi发现,感谢 [Feat] 增加Compiler相关定义,将开发BytecodeVM [Tip] Evaluator进入Bug fix阶段,新功能延缓开发。转向VM
125 lines
3.7 KiB
C++
125 lines
3.7 KiB
C++
#pragma once
|
|
|
|
/*
|
|
|
|
从树遍历到虚拟机!
|
|
|
|
*/
|
|
|
|
#include "Core/fig_string.hpp"
|
|
#include "Utils/magic_enum/magic_enum.hpp"
|
|
#include <cstdint>
|
|
#include <format>
|
|
#include <string_view>
|
|
|
|
namespace Fig
|
|
{
|
|
using OpCodeType = uint8_t;
|
|
enum class Bytecode : OpCodeType
|
|
{
|
|
HALT = 0x01, // 程序终止,后跟 8 位退出码
|
|
|
|
POP = 0x10,
|
|
|
|
LOAD_NULL = 0x20,
|
|
LOAD_TRUE = 0x21,
|
|
LOAD_FALSE = 0x22,
|
|
LOAD_CON8 = 0x23, // 跟 8 位索引 (0 - 255)
|
|
LOAD_CON16 = 0x24, // 跟 16 位索引 (255 - 65535)
|
|
LOAD_CON32 = 0x25, // 跟 32 位索引 (65536 - 2^32-1)
|
|
|
|
ADD = 0x30, // +
|
|
SUB = 0x31, // -
|
|
MUL = 0x32, // *
|
|
DIV = 0x33, // /
|
|
MOD = 0x34, // %
|
|
|
|
AND = 0x40, // &
|
|
OR = 0x41, // |
|
|
XOR = 0x42, // ~
|
|
NOT = 0x43, // ! (not)
|
|
|
|
EQ = 0x50, // ==
|
|
GT = 0x51, // >
|
|
GTEQ = 0x52, // >=
|
|
LT = 0x53, // <
|
|
LTEQ = 0x54, // <=
|
|
|
|
JUMP16 = 0x60, // 跟 16 位索引 无条件
|
|
JUMP32 = 0x61, // 跟 32 位索引 无条件
|
|
|
|
JUMP16_IF_TRUE = 0x62, // 跟 16 位索引 栈顶为真跳转
|
|
JUMP32_IF_TRUE = 0x63, // 跟 32 位索引 栈顶为真跳转
|
|
|
|
JUMP16_IF_FALSE = 0x64, // 跟 16 位索引 栈顶为假跳转
|
|
JUMP32_IF_FALSE = 0x65, // 跟 32 位索引 栈顶为假跳转
|
|
|
|
LOAD_LOCAL16 = 0x70, // 后跟 16 位索引
|
|
LOAD_LOCAL32 = 0x71, // 后跟 32 位索引
|
|
};
|
|
|
|
inline FString bytecode2string(Bytecode code)
|
|
{
|
|
const std::string_view &name = magic_enum::enum_name(code);
|
|
return FString(FStringView(name));
|
|
}
|
|
|
|
inline FString reverseCompile(const std::vector<uint8_t> &src)
|
|
{
|
|
assert(src.size() >= 1);
|
|
|
|
FString result;
|
|
|
|
using enum Bytecode;
|
|
for (size_t i = 0; i < src.size();)
|
|
{
|
|
Bytecode code = Bytecode(src[i]);
|
|
switch (code)
|
|
{
|
|
case HALT: {
|
|
uint8_t quitCode = src[++i];
|
|
result += FString(std::format("HALT {}", static_cast<uint8_t>(quitCode))) + u8"\n";
|
|
break;
|
|
}
|
|
case LOAD_CON8: {
|
|
uint8_t id = src[++i];
|
|
result += FString(std::format("LOAD_CON8 {}", static_cast<uint8_t>(id))) + u8"\n";
|
|
break;
|
|
}
|
|
case LOAD_CON16:
|
|
case JUMP16:
|
|
case JUMP16_IF_TRUE:
|
|
case JUMP16_IF_FALSE:
|
|
case LOAD_LOCAL16: {
|
|
uint8_t high = src[++i];
|
|
uint8_t low = src[++i];
|
|
int32_t id = (high << 8) | low;
|
|
result += FString(std::format("{} {}", bytecode2string(code).toBasicString(), id))
|
|
+ u8"\n";
|
|
break;
|
|
}
|
|
|
|
case LOAD_CON32:
|
|
case JUMP32:
|
|
case JUMP32_IF_TRUE:
|
|
case JUMP32_IF_FALSE:
|
|
case LOAD_LOCAL32: {
|
|
uint32_t b0 = static_cast<uint32_t>(src[++i]);
|
|
uint32_t b1 = static_cast<uint32_t>(src[++i]);
|
|
uint32_t b2 = static_cast<uint32_t>(src[++i]);
|
|
uint32_t b3 = static_cast<uint32_t>(src[++i]);
|
|
|
|
uint32_t id = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
|
|
result += FString(std::format("{} {}", bytecode2string(code).toBasicString(), id))
|
|
+ u8"\n";
|
|
break;
|
|
}
|
|
default: {
|
|
result += bytecode2string(code) + u8"\n";
|
|
}
|
|
}
|
|
++i;
|
|
}
|
|
return result;
|
|
}
|
|
}; // namespace Fig
|