2289 lines
102 KiB
C++
2289 lines
102 KiB
C++
#include "CrossLang.hpp"
|
|
#include <array>
|
|
#include <cstring>
|
|
#include <iostream>
|
|
#include <map>
|
|
#include <variant>
|
|
|
|
namespace Tesses::CrossLang {
|
|
void Write(std::shared_ptr<Tesses::Framework::Streams::Stream> strm,
|
|
uint8_t *buffer, size_t len) {
|
|
strm->WriteBlock(buffer, len);
|
|
}
|
|
void WriteInt(std::shared_ptr<Tesses::Framework::Streams::Stream> strm,
|
|
uint32_t v) {
|
|
uint8_t buffer[4];
|
|
BitConverter::FromUint32BE(buffer[0], v);
|
|
Write(strm, buffer, 4);
|
|
}
|
|
void WriteString(std::shared_ptr<Tesses::Framework::Streams::Stream> strm,
|
|
std::string v) {
|
|
WriteInt(strm, (uint32_t)v.size());
|
|
Write(strm, (uint8_t *)v.data(), v.size());
|
|
}
|
|
|
|
CodeGen::~CodeGen() {
|
|
for (auto &item : this->chunks) {
|
|
for (auto instr : item.second)
|
|
delete instr;
|
|
}
|
|
}
|
|
|
|
SyntaxNode CodeGen::OptimizeNode(SyntaxNode n) {
|
|
if (std::holds_alternative<AdvancedSyntaxNode>(n)) {
|
|
auto &asn = std::get<AdvancedSyntaxNode>(n);
|
|
if (asn.nodeName == AddExpression && asn.nodes.size() == 2) {
|
|
auto leftNode = OptimizeNode(asn.nodes[0]);
|
|
auto rightNode = OptimizeNode(asn.nodes[1]);
|
|
|
|
if (std::holds_alternative<int64_t>(leftNode) &&
|
|
std::holds_alternative<int64_t>(rightNode)) {
|
|
return std::get<int64_t>(leftNode) +
|
|
std::get<int64_t>(rightNode);
|
|
}
|
|
if (std::holds_alternative<double>(leftNode) &&
|
|
std::holds_alternative<double>(rightNode)) {
|
|
return std::get<double>(leftNode) + std::get<double>(rightNode);
|
|
}
|
|
if (std::holds_alternative<int64_t>(leftNode) &&
|
|
std::holds_alternative<double>(rightNode)) {
|
|
return (double)std::get<int64_t>(leftNode) +
|
|
std::get<double>(rightNode);
|
|
}
|
|
if (std::holds_alternative<double>(leftNode) &&
|
|
std::holds_alternative<int64_t>(rightNode)) {
|
|
return std::get<double>(leftNode) +
|
|
(double)std::get<int64_t>(rightNode);
|
|
}
|
|
if (std::holds_alternative<std::string>(leftNode) &&
|
|
std::holds_alternative<std::string>(rightNode)) {
|
|
return std::get<std::string>(leftNode) +
|
|
std::get<std::string>(rightNode);
|
|
}
|
|
if (std::holds_alternative<std::string>(leftNode) &&
|
|
std::holds_alternative<char>(rightNode)) {
|
|
return std::get<std::string>(leftNode) +
|
|
std::get<char>(rightNode);
|
|
}
|
|
if (std::holds_alternative<char>(leftNode) &&
|
|
std::holds_alternative<std::string>(rightNode)) {
|
|
return std::get<char>(leftNode) +
|
|
std::get<std::string>(rightNode);
|
|
}
|
|
}
|
|
if (asn.nodeName == SubExpression && asn.nodes.size() == 2) {
|
|
auto leftNode = OptimizeNode(asn.nodes[0]);
|
|
auto rightNode = OptimizeNode(asn.nodes[1]);
|
|
|
|
if (std::holds_alternative<int64_t>(leftNode) &&
|
|
std::holds_alternative<int64_t>(rightNode)) {
|
|
return std::get<int64_t>(leftNode) -
|
|
std::get<int64_t>(rightNode);
|
|
}
|
|
if (std::holds_alternative<double>(leftNode) &&
|
|
std::holds_alternative<double>(rightNode)) {
|
|
return std::get<double>(leftNode) - std::get<double>(rightNode);
|
|
}
|
|
if (std::holds_alternative<int64_t>(leftNode) &&
|
|
std::holds_alternative<double>(rightNode)) {
|
|
return (double)std::get<int64_t>(leftNode) -
|
|
std::get<double>(rightNode);
|
|
}
|
|
if (std::holds_alternative<double>(leftNode) &&
|
|
std::holds_alternative<int64_t>(rightNode)) {
|
|
return std::get<double>(leftNode) -
|
|
(double)std::get<int64_t>(rightNode);
|
|
}
|
|
}
|
|
if (asn.nodeName == CommaExpression && asn.nodes.size() == 2) {
|
|
return AdvancedSyntaxNode::Create(
|
|
CommaExpression, true,
|
|
{OptimizeNode(asn.nodes[0]), OptimizeNode(asn.nodes[1])});
|
|
}
|
|
if (asn.nodeName == ScopeNode) {
|
|
if (asn.nodes.empty()) {
|
|
asn.nodeName = NodeList;
|
|
return asn;
|
|
} else {
|
|
for (auto &item : asn.nodes) {
|
|
item = OptimizeNode(item);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return n;
|
|
}
|
|
|
|
/*
|
|
0: false,
|
|
1: true,
|
|
2: null,
|
|
3: Long,
|
|
4: Double,
|
|
5: Char
|
|
6: String,
|
|
7: List,
|
|
8: Dictionary,
|
|
9: ByteArray (embed),
|
|
10: Stream (embedstrm),
|
|
11: VFS (embeddir),
|
|
12: ClosureOfEmbedStream (used by embeddir)
|
|
*/
|
|
|
|
void CodeGen::WriteMetadataObject(std::vector<uint8_t> &bytes, SyntaxNode n) {
|
|
if (std::holds_alternative<bool>(n)) {
|
|
bytes.push_back(std::get<bool>(n) ? 1 : 0);
|
|
return;
|
|
}
|
|
if (std::holds_alternative<std::nullptr_t>(n)) {
|
|
bytes.push_back(2);
|
|
return;
|
|
}
|
|
if (std::holds_alternative<int64_t>(n)) {
|
|
auto num = std::get<int64_t>(n);
|
|
bytes.push_back(3);
|
|
size_t offset = bytes.size();
|
|
bytes.resize(offset + 8);
|
|
BitConverter::FromUint64BE(bytes[offset], num);
|
|
return;
|
|
}
|
|
if (std::holds_alternative<double>(n)) {
|
|
auto num = std::get<double>(n);
|
|
bytes.push_back(4);
|
|
size_t offset = bytes.size();
|
|
bytes.resize(offset + 8);
|
|
BitConverter::FromDoubleBE(bytes[offset], num);
|
|
return;
|
|
}
|
|
if (std::holds_alternative<char>(n)) {
|
|
auto chr = std::get<char>(n);
|
|
bytes.push_back(5);
|
|
bytes.push_back((uint8_t)chr);
|
|
return;
|
|
}
|
|
if (std::holds_alternative<std::string>(n)) {
|
|
auto &str = std::get<std::string>(n);
|
|
bytes.push_back(6);
|
|
size_t offset = bytes.size();
|
|
bytes.resize(offset + 4);
|
|
BitConverter::FromUint32BE(bytes[offset], GetString(str));
|
|
return;
|
|
}
|
|
if (std::holds_alternative<AdvancedSyntaxNode>(n)) {
|
|
auto &asn = std::get<AdvancedSyntaxNode>(n);
|
|
if (asn.nodeName == ArrayExpression) {
|
|
std::vector<SyntaxNode> itms;
|
|
if (asn.nodes.size() > 0)
|
|
|
|
GetFunctionArgs(itms, asn.nodes[0]);
|
|
bytes.push_back(7);
|
|
size_t offset = bytes.size();
|
|
bytes.resize(offset + 4);
|
|
BitConverter::FromUint32BE(bytes[offset], (uint32_t)itms.size());
|
|
for (auto &item : itms) {
|
|
WriteMetadataObject(bytes, item);
|
|
}
|
|
return;
|
|
}
|
|
if (asn.nodeName == DictionaryExpression) {
|
|
std::vector<SyntaxNode> itms;
|
|
if (asn.nodes.size() > 0)
|
|
|
|
GetFunctionArgs(itms, asn.nodes[0]);
|
|
bytes.push_back(8);
|
|
size_t offset = bytes.size();
|
|
bytes.resize(offset + 4);
|
|
BitConverter::FromUint32BE(bytes[offset], (uint32_t)itms.size());
|
|
for (auto &item : itms) {
|
|
if (std::holds_alternative<AdvancedSyntaxNode>(item)) {
|
|
auto tkn = std::get<AdvancedSyntaxNode>(item);
|
|
if (tkn.nodeName == GetVariableExpression &&
|
|
!tkn.nodes.empty()) {
|
|
if (std::holds_alternative<std::string>(tkn.nodes[0])) {
|
|
size_t offset2 = bytes.size();
|
|
bytes.resize(offset2 + 4);
|
|
BitConverter::FromUint32BE(
|
|
bytes[offset2],
|
|
GetString(std::get<std::string>(tkn.nodes[0])));
|
|
bytes.push_back(2);
|
|
|
|
} else {
|
|
|
|
size_t offset2 = bytes.size();
|
|
bytes.resize(offset2 + 4);
|
|
BitConverter::FromUint32BE(bytes[offset2],
|
|
GetString("__unknown"));
|
|
bytes.push_back(2);
|
|
}
|
|
} else if (tkn.nodeName == AssignExpression &&
|
|
tkn.nodes.size() == 2 &&
|
|
std::holds_alternative<AdvancedSyntaxNode>(
|
|
tkn.nodes[0])) {
|
|
auto myTn = std::get<AdvancedSyntaxNode>(tkn.nodes[0]);
|
|
if (myTn.nodeName == GetVariableExpression &&
|
|
!myTn.nodes.empty()) {
|
|
if (std::holds_alternative<std::string>(
|
|
myTn.nodes[0])) {
|
|
size_t offset2 = bytes.size();
|
|
bytes.resize(offset2 + 4);
|
|
BitConverter::FromUint32BE(
|
|
bytes[offset2],
|
|
GetString(
|
|
std::get<std::string>(myTn.nodes[0])));
|
|
WriteMetadataObject(bytes, tkn.nodes[1]);
|
|
|
|
} else {
|
|
|
|
size_t offset2 = bytes.size();
|
|
bytes.resize(offset2 + 4);
|
|
BitConverter::FromUint32BE(
|
|
bytes[offset2], GetString("__unknown"));
|
|
bytes.push_back(2);
|
|
}
|
|
} else {
|
|
|
|
size_t offset2 = bytes.size();
|
|
bytes.resize(offset2 + 4);
|
|
BitConverter::FromUint32BE(bytes[offset2],
|
|
GetString("__unknown"));
|
|
bytes.push_back(2);
|
|
}
|
|
} else {
|
|
|
|
size_t offset2 = bytes.size();
|
|
bytes.resize(offset2 + 4);
|
|
BitConverter::FromUint32BE(bytes[offset2],
|
|
GetString("__unknown"));
|
|
bytes.push_back(2);
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
if (asn.nodeName == EmbedExpression) {
|
|
if (!asn.nodes.empty() &&
|
|
std::holds_alternative<std::string>(asn.nodes[0])) {
|
|
auto &filename = std::get<std::string>(asn.nodes[0]);
|
|
bytes.push_back(9);
|
|
size_t offset = bytes.size();
|
|
bytes.resize(offset + 4);
|
|
BitConverter::FromUint32BE(
|
|
bytes[offset],
|
|
GetResource(std::make_shared<ResourceFile>(filename)));
|
|
return;
|
|
}
|
|
}
|
|
if (asn.nodeName == EmbedStreamExpression) {
|
|
if (!asn.nodes.empty() &&
|
|
std::holds_alternative<std::string>(asn.nodes[0])) {
|
|
auto &filename = std::get<std::string>(asn.nodes[0]);
|
|
bytes.push_back(10);
|
|
size_t offset = bytes.size();
|
|
bytes.resize(offset + 4);
|
|
BitConverter::FromUint32BE(
|
|
bytes[offset],
|
|
GetResource(std::make_shared<ResourceFile>(filename)));
|
|
return;
|
|
}
|
|
}
|
|
if (asn.nodeName == EmbedDirectoryExpression) {
|
|
if (!asn.nodes.empty() &&
|
|
std::holds_alternative<std::string>(asn.nodes[0])) {
|
|
auto &filename = std::get<std::string>(asn.nodes[0]);
|
|
bytes.push_back(11);
|
|
|
|
std::function<void(Tesses::Framework::Filesystem::VFSPath path)>
|
|
embedDir;
|
|
embedDir =
|
|
[&](Tesses::Framework::Filesystem::VFSPath path) -> void {
|
|
bytes.push_back(8);
|
|
std::vector<
|
|
std::pair<Tesses::Framework::Filesystem::VFSPath, bool>>
|
|
entries;
|
|
if (embedFS != nullptr && embedFS->DirectoryExists(path))
|
|
for (auto &item : embedFS->EnumeratePaths(path)) {
|
|
if (embedFS->DirectoryExists(item))
|
|
entries.emplace_back(item, true);
|
|
else if (embedFS->FileExists(item))
|
|
entries.emplace_back(item, false);
|
|
|
|
/*GenNode(instructions,item.GetFileName(),scope,contscope,brkscope,contI,brkI);
|
|
if(embedFS->DirectoryExists(item))
|
|
{
|
|
embedDir(item);
|
|
}
|
|
else if(embedFS->RegularFileExists(item))
|
|
{
|
|
auto ce =
|
|
AdvancedSyntaxNode::Create(ClosureExpression,true,{
|
|
AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}),
|
|
AdvancedSyntaxNode::Create(ReturnStatement,false,{
|
|
AdvancedSyntaxNode::Create(EmbedStreamExpression,true,{item.ToString()})
|
|
})
|
|
});
|
|
GenNode(instructions,ce,scope,contscope,brkscope,contI,brkI);
|
|
}
|
|
else {
|
|
instructions.push_back(new
|
|
SimpleInstruction(PUSHUNDEFINED));
|
|
}
|
|
|
|
instructions.push_back(new
|
|
SimpleInstruction(APPENDDICT));*/
|
|
}
|
|
size_t offset = bytes.size();
|
|
bytes.resize(offset + 4);
|
|
BitConverter::FromUint32BE(bytes[offset],
|
|
(uint32_t)entries.size());
|
|
for (auto &item : entries) {
|
|
offset = bytes.size();
|
|
bytes.resize(offset + 4);
|
|
BitConverter::FromUint32BE(
|
|
bytes[offset], GetString(item.first.GetFileName()));
|
|
if (item.second)
|
|
embedDir(item.first);
|
|
else {
|
|
bytes.push_back(12);
|
|
offset = bytes.size();
|
|
bytes.resize(offset + 4);
|
|
bytes.resize(offset + 4);
|
|
BitConverter::FromUint32BE(
|
|
bytes[offset],
|
|
GetResource(std::make_shared<ResourceFile>(
|
|
item.first.ToString())));
|
|
}
|
|
}
|
|
};
|
|
embedDir(filename);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
bytes.push_back(2);
|
|
}
|
|
|
|
void CodeGen::Save(std::shared_ptr<Tesses::Framework::Streams::Stream> stream) {
|
|
TVMVersion runtime_version(
|
|
CROSSLANG_BYTECODE_MAJOR, CROSSLANG_BYTECODE_MINOR,
|
|
CROSSLANG_BYTECODE_PATCH, CROSSLANG_BYTECODE_BUILD,
|
|
CROSSLANG_BYTECODE_VERSIONSTAGE);
|
|
uint8_t buffer[18];
|
|
memcpy(buffer, "TCROSSVM", 8);
|
|
runtime_version.ToArray(buffer + 8);
|
|
version.ToArray(buffer + 13);
|
|
Write(stream, buffer, 18);
|
|
uint32_t sections = 5;
|
|
uint32_t name = GetString(this->name);
|
|
uint32_t info = GetString(this->info);
|
|
|
|
for (auto &dep : this->dependencies) {
|
|
GetString(dep.first);
|
|
sections++;
|
|
}
|
|
for (auto &tool : this->tools) {
|
|
GetString(tool.first);
|
|
sections++;
|
|
}
|
|
for (auto &meta : this->meta) {
|
|
sections++;
|
|
}
|
|
if (!this->icon.empty()) {
|
|
this->GetResource(std::make_shared<ResourceFile>(this->icon));
|
|
}
|
|
for (auto &res : this->res)
|
|
sections++;
|
|
|
|
if (!this->icon.empty())
|
|
sections++;
|
|
if (!this->classes.empty())
|
|
sections++;
|
|
|
|
WriteInt(stream, sections);
|
|
uint32_t strSz = 4;
|
|
for (auto &s : this->strs) {
|
|
strSz += (uint32_t)s.size() + 4;
|
|
}
|
|
memcpy(buffer, "STRS", 4);
|
|
Write(stream, buffer, 4);
|
|
WriteInt(stream, strSz); // even though its ignored
|
|
WriteInt(stream, this->strs.size());
|
|
for (auto &str : this->strs)
|
|
WriteString(stream, str);
|
|
memcpy(buffer, "NAME", 4);
|
|
Write(stream, buffer, 4);
|
|
WriteInt(stream, 4);
|
|
WriteInt(stream, name);
|
|
memcpy(buffer, "INFO", 4);
|
|
Write(stream, buffer, 4);
|
|
WriteInt(stream, 4);
|
|
WriteInt(stream, info);
|
|
|
|
for (auto &dep : this->dependencies) {
|
|
memcpy(buffer, "DEPS", 4);
|
|
Write(stream, buffer, 4);
|
|
WriteInt(stream, 9); // even though its ignored
|
|
WriteInt(stream, GetString(dep.first));
|
|
dep.second.ToArray(buffer);
|
|
Write(stream, buffer, 5);
|
|
}
|
|
for (auto &tool : this->tools) {
|
|
memcpy(buffer, "TOOL", 4);
|
|
Write(stream, buffer, 4);
|
|
WriteInt(stream, 9); // even though its ignored
|
|
WriteInt(stream, GetString(tool.first));
|
|
tool.second.ToArray(buffer);
|
|
Write(stream, buffer, 5);
|
|
}
|
|
|
|
uint32_t fnLen = 4;
|
|
|
|
for (auto &fn : this->funcs) {
|
|
fnLen += (fn.first.size() + 2) * 4;
|
|
}
|
|
|
|
memcpy(buffer, "FUNS", 4);
|
|
Write(stream, buffer, 4);
|
|
WriteInt(stream, fnLen);
|
|
WriteInt(stream, (uint32_t)this->funcs.size());
|
|
for (auto &fn : this->funcs) {
|
|
WriteInt(stream, (uint32_t)fn.first.size());
|
|
for (auto namePart : fn.first) {
|
|
WriteInt(stream, namePart);
|
|
}
|
|
WriteInt(stream, fn.second);
|
|
}
|
|
|
|
uint32_t clength = 4;
|
|
for (auto &chunk : this->chunks) {
|
|
clength += (2 + chunk.first.size()) * 4;
|
|
size_t offset = 0;
|
|
std::map<std::string, int64_t> items;
|
|
|
|
for (auto instr : chunk.second) {
|
|
|
|
auto lbl = dynamic_cast<LabelInstruction *>(instr);
|
|
if (lbl != nullptr) {
|
|
items[lbl->label] = offset;
|
|
}
|
|
|
|
offset += instr->Size();
|
|
}
|
|
|
|
clength += (uint32_t)offset;
|
|
|
|
for (auto instr : chunk.second) {
|
|
auto jmp = dynamic_cast<LabelableInstruction *>(instr);
|
|
if (jmp != nullptr) {
|
|
jmp->n = items[jmp->label];
|
|
}
|
|
}
|
|
}
|
|
|
|
memcpy(buffer, "CHKS", 4);
|
|
Write(stream, buffer, 4);
|
|
WriteInt(stream, clength);
|
|
WriteInt(stream, (uint32_t)this->chunks.size());
|
|
for (auto &chunk : this->chunks) {
|
|
std::vector<uint8_t> buffer;
|
|
WriteInt(stream, (uint32_t)chunk.first.size());
|
|
for (auto arg : chunk.first) {
|
|
WriteInt(stream, arg);
|
|
}
|
|
for (auto instr : chunk.second) {
|
|
instr->Write(buffer);
|
|
}
|
|
WriteInt(stream, (uint32_t)buffer.size());
|
|
Write(stream, buffer.data(), buffer.size());
|
|
}
|
|
|
|
if (!classes.empty()) {
|
|
uint32_t len = 4;
|
|
for (auto &cls : classes) {
|
|
len += 8;
|
|
len += cls.name.size() * 4;
|
|
len += 4;
|
|
len += cls.inherits.size() * 4;
|
|
len += 4;
|
|
for (auto &clsEnt : cls.entries) {
|
|
len += 17;
|
|
for (auto &arg : clsEnt.arguments)
|
|
len += 4;
|
|
}
|
|
}
|
|
|
|
memcpy(buffer, "CLSS", 4);
|
|
Write(stream, buffer, 4);
|
|
WriteInt(stream, len);
|
|
WriteInt(stream, (uint32_t)classes.size());
|
|
for (auto &cls : classes) {
|
|
WriteInt(stream, cls.documentation);
|
|
WriteInt(stream, (uint32_t)cls.name.size());
|
|
for (auto namePart : cls.name)
|
|
WriteInt(stream, namePart);
|
|
|
|
WriteInt(stream, (uint32_t)cls.inherits.size());
|
|
for (auto inhPart : cls.inherits)
|
|
WriteInt(stream, inhPart);
|
|
|
|
WriteInt(stream, (uint32_t)cls.entries.size());
|
|
|
|
for (auto &ent : cls.entries) {
|
|
buffer[0] = ent.type;
|
|
Write(stream, buffer, 1);
|
|
WriteInt(stream, ent.documentation);
|
|
WriteInt(stream, ent.name);
|
|
WriteInt(stream, (uint32_t)ent.arguments.size());
|
|
for (auto ar : ent.arguments) {
|
|
WriteInt(stream, ar);
|
|
}
|
|
WriteInt(stream, ent.closure);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (auto &reso : res) {
|
|
memcpy(buffer, "RESO", 4);
|
|
Write(stream, buffer, 4);
|
|
WriteInt(stream, reso->GetLength(embedFS));
|
|
reso->Write(stream);
|
|
}
|
|
if (!this->icon.empty()) {
|
|
memcpy(buffer, "ICON", 4);
|
|
Write(stream, buffer, 4);
|
|
WriteInt(stream, 4);
|
|
WriteInt(stream,
|
|
this->GetResource(std::make_shared<ResourceFile>(this->icon)));
|
|
}
|
|
for (auto &meta : this->meta) {
|
|
memcpy(buffer, "META", 4);
|
|
Write(stream, buffer, 4);
|
|
WriteInt(stream, (uint32_t)meta.size());
|
|
Write(stream, meta.data(), meta.size());
|
|
}
|
|
}
|
|
|
|
size_t SimpleInstruction::Size() { return 1; }
|
|
SimpleInstruction::SimpleInstruction(Instruction instr) {
|
|
this->instruction = instr;
|
|
}
|
|
void SimpleInstruction::Write(std::vector<uint8_t> &instr) {
|
|
instr.push_back(instruction);
|
|
}
|
|
|
|
ScopeEndTimesInstruction::ScopeEndTimesInstruction(uint32_t s) { this->n = s; }
|
|
size_t ScopeEndTimesInstruction::Size() { return 5; }
|
|
void ScopeEndTimesInstruction::Write(std::vector<uint8_t> &instr) {
|
|
instr.push_back(SCOPEENDTIMES);
|
|
std::array<uint8_t, 4> buff;
|
|
BitConverter::FromUint32BE(buff[0], this->n);
|
|
instr.insert(instr.end(), buff.begin(), buff.end());
|
|
}
|
|
|
|
LabelInstruction::LabelInstruction(std::string lbl) { this->label = lbl; }
|
|
|
|
size_t LabelInstruction::Size() { return 0; }
|
|
|
|
void LabelInstruction::Write(std::vector<uint8_t> &instr) {
|
|
// label instructions do not write a thing
|
|
}
|
|
|
|
JumpStyleInstruction::JumpStyleInstruction(Instruction instr, std::string lbl) {
|
|
this->type = instr;
|
|
this->label = lbl;
|
|
this->n = 0;
|
|
}
|
|
|
|
size_t JumpStyleInstruction::Size() { return 5; }
|
|
void JumpStyleInstruction::Write(std::vector<uint8_t> &instr) {
|
|
instr.push_back((uint8_t)type);
|
|
std::array<uint8_t, 4> buff;
|
|
BitConverter::FromUint32BE(buff[0], this->n);
|
|
instr.insert(instr.end(), buff.begin(), buff.end());
|
|
}
|
|
|
|
size_t LabelableInstruction::Size() { return 4; }
|
|
void LabelableInstruction::Write(std::vector<uint8_t> &instr) {
|
|
|
|
std::array<uint8_t, 4> buff;
|
|
BitConverter::FromUint32BE(buff[0], this->n);
|
|
instr.insert(instr.end(), buff.begin(), buff.end());
|
|
}
|
|
StringInstruction::StringInstruction(uint32_t s) { this->n = s; }
|
|
size_t StringInstruction::Size() { return 5; }
|
|
void StringInstruction::Write(std::vector<uint8_t> &instr) {
|
|
instr.push_back(PUSHSTRING);
|
|
std::array<uint8_t, 4> buff;
|
|
BitConverter::FromUint32BE(buff[0], this->n);
|
|
instr.insert(instr.end(), buff.begin(), buff.end());
|
|
}
|
|
EmbedInstruction::EmbedInstruction(uint32_t s) { this->n = s; }
|
|
size_t EmbedInstruction::Size() { return 5; }
|
|
void EmbedInstruction::Write(std::vector<uint8_t> &instr) {
|
|
instr.push_back(PUSHRESOURCE);
|
|
std::array<uint8_t, 4> buff;
|
|
BitConverter::FromUint32BE(buff[0], this->n);
|
|
instr.insert(instr.end(), buff.begin(), buff.end());
|
|
}
|
|
EmbedStreamInstruction::EmbedStreamInstruction(uint32_t s) { this->n = s; }
|
|
size_t EmbedStreamInstruction::Size() { return 5; }
|
|
void EmbedStreamInstruction::Write(std::vector<uint8_t> &instr) {
|
|
instr.push_back(PUSHRESOURCESTREAM);
|
|
std::array<uint8_t, 4> buff;
|
|
BitConverter::FromUint32BE(buff[0], this->n);
|
|
instr.insert(instr.end(), buff.begin(), buff.end());
|
|
}
|
|
ClosureInstruction::ClosureInstruction(uint32_t s, bool hasScope) {
|
|
this->n = s;
|
|
this->hasScope = hasScope;
|
|
}
|
|
size_t ClosureInstruction::Size() { return 5; }
|
|
void ClosureInstruction::Write(std::vector<uint8_t> &instr) {
|
|
instr.push_back(this->hasScope ? PUSHCLOSURE : PUSHSCOPELESSCLOSURE);
|
|
std::array<uint8_t, 4> buff;
|
|
BitConverter::FromUint32BE(buff[0], this->n);
|
|
instr.insert(instr.end(), buff.begin(), buff.end());
|
|
}
|
|
|
|
DoubleInstruction::DoubleInstruction(double s) { this->n = s; }
|
|
size_t DoubleInstruction::Size() { return 9; }
|
|
void DoubleInstruction::Write(std::vector<uint8_t> &instr) {
|
|
instr.push_back(PUSHDOUBLE);
|
|
std::array<uint8_t, 8> buff;
|
|
BitConverter::FromDoubleBE(buff[0], this->n);
|
|
instr.insert(instr.end(), buff.begin(), buff.end());
|
|
}
|
|
|
|
CharInstruction::CharInstruction(char s) { this->n = s; }
|
|
size_t CharInstruction::Size() { return 2; }
|
|
void CharInstruction::Write(std::vector<uint8_t> &instr) {
|
|
instr.push_back(PUSHCHAR);
|
|
uint8_t buff[8];
|
|
instr.push_back((uint8_t)this->n);
|
|
}
|
|
LongInstruction::LongInstruction(int64_t s) { this->n = s; }
|
|
size_t LongInstruction::Size() { return 9; }
|
|
void LongInstruction::Write(std::vector<uint8_t> &instr) {
|
|
instr.push_back(PUSHLONG);
|
|
std::array<uint8_t, 8> buff;
|
|
BitConverter::FromUint64BE(buff[0], (uint64_t)this->n);
|
|
instr.insert(instr.end(), buff.begin(), buff.end());
|
|
}
|
|
uint32_t CodeGen::GetString(std::string str) {
|
|
for (uint32_t i = 0; i < (uint32_t)this->strs.size(); i++) {
|
|
if (this->strs[i] == str)
|
|
return i;
|
|
}
|
|
uint32_t strI = (uint32_t)this->strs.size();
|
|
this->strs.push_back(str);
|
|
return strI;
|
|
}
|
|
uint32_t CodeGen::GetResource(std::shared_ptr<ResourceBase> resource) {
|
|
for (uint32_t i = 0; i < (uint32_t)this->res.size(); i++) {
|
|
if (this->res[i]->IsEqual(resource.get()))
|
|
return i;
|
|
}
|
|
uint32_t resI = (uint32_t)this->res.size();
|
|
this->res.push_back(resource);
|
|
return resI;
|
|
}
|
|
#define ONE_EXPR(EXPRESSION, INSTRUCTION) \
|
|
if (adv.nodeName == EXPRESSION && adv.nodes.size() == 1) { \
|
|
GenNode(instructions, adv.nodes[0], scope, contscope, brkscope, contI, \
|
|
brkI); \
|
|
instructions.push_back(new SimpleInstruction(INSTRUCTION)); \
|
|
}
|
|
#define TWO_EXPR(EXPRESSION, INSTRUCTION) \
|
|
if (adv.nodeName == EXPRESSION && adv.nodes.size() == 2) { \
|
|
GenNode(instructions, adv.nodes[0], scope, contscope, brkscope, contI, \
|
|
brkI); \
|
|
GenNode(instructions, adv.nodes[1], scope, contscope, brkscope, contI, \
|
|
brkI); \
|
|
instructions.push_back(new SimpleInstruction(INSTRUCTION)); \
|
|
}
|
|
|
|
SyntaxNode CodeGen::StringifyListOfVars(SyntaxNode n) {
|
|
if (std::holds_alternative<std::string>(n)) {
|
|
return n;
|
|
} else if (std::holds_alternative<AdvancedSyntaxNode>(n)) {
|
|
auto itemA = std::get<AdvancedSyntaxNode>(n);
|
|
if (itemA.nodeName == GetVariableExpression &&
|
|
itemA.nodes.size() == 1 &&
|
|
std::holds_alternative<std::string>(itemA.nodes[0])) {
|
|
return std::get<std::string>(itemA.nodes[0]);
|
|
} else if (itemA.nodeName == CommaExpression &&
|
|
itemA.nodes.size() == 2) {
|
|
return AdvancedSyntaxNode::Create(
|
|
CommaExpression, true,
|
|
{StringifyListOfVars(itemA.nodes[0]),
|
|
StringifyListOfVars(itemA.nodes[1])});
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
|
SyntaxNode n, int32_t scope, int32_t contscope,
|
|
int32_t brkscope, int32_t contI, int32_t brkI) {
|
|
if (std::holds_alternative<std::nullptr_t>(n)) {
|
|
instructions.push_back(new SimpleInstruction(PUSHNULL));
|
|
} else if (std::holds_alternative<Undefined>(n)) {
|
|
instructions.push_back(new SimpleInstruction(PUSHUNDEFINED));
|
|
} else if (std::holds_alternative<bool>(n)) {
|
|
instructions.push_back(
|
|
new SimpleInstruction(std::get<bool>(n) ? PUSHTRUE : PUSHFALSE));
|
|
} else if (std::holds_alternative<std::string>(n)) {
|
|
instructions.push_back(
|
|
new StringInstruction(GetString(std::get<std::string>(n))));
|
|
} else if (std::holds_alternative<char>(n)) {
|
|
instructions.push_back(new CharInstruction(std::get<char>(n)));
|
|
} else if (std::holds_alternative<int64_t>(n)) {
|
|
instructions.push_back(new LongInstruction(std::get<int64_t>(n)));
|
|
} else if (std::holds_alternative<double>(n)) {
|
|
instructions.push_back(new DoubleInstruction(std::get<double>(n)));
|
|
} else if (std::holds_alternative<std::vector<uint8_t>>(n)) {
|
|
ResourceByteArray ba;
|
|
ba.data = std::get<std::vector<uint8_t>>(n);
|
|
instructions.push_back(new EmbedInstruction(
|
|
GetResource(std::make_shared<ResourceByteArray>(ba))));
|
|
} else if (std::holds_alternative<AdvancedSyntaxNode>(n)) {
|
|
auto adv = std::get<AdvancedSyntaxNode>(n);
|
|
ONE_EXPR(NotExpression, NOT)
|
|
ONE_EXPR(BitwiseNotExpression, BITWISENOT)
|
|
ONE_EXPR(NegativeExpression, NEGATIVE)
|
|
TWO_EXPR(AddExpression, ADD)
|
|
TWO_EXPR(SubExpression, SUB)
|
|
TWO_EXPR(TimesExpression, TIMES)
|
|
TWO_EXPR(DivideExpression, DIVIDE)
|
|
TWO_EXPR(ModExpression, MODULO)
|
|
TWO_EXPR(LeftShiftExpression, LEFTSHIFT)
|
|
TWO_EXPR(RightShiftExpression, RIGHTSHIFT)
|
|
TWO_EXPR(BitwiseOrExpression, BITWISEOR)
|
|
TWO_EXPR(BitwiseAndExpression, BITWISEAND)
|
|
TWO_EXPR(LessThanExpression, LESSTHAN)
|
|
TWO_EXPR(GreaterThanExpression, GREATERTHAN)
|
|
TWO_EXPR(LessThanEqualsExpression, LESSTHANEQ)
|
|
TWO_EXPR(GreaterThanEqualsExpression, GREATERTHANEQ)
|
|
TWO_EXPR(NotEqualsExpression, NEQ)
|
|
TWO_EXPR(EqualsExpression, EQ)
|
|
TWO_EXPR(XOrExpression, XOR)
|
|
if (adv.nodeName == GetPrivateExpression) {
|
|
instructions.push_back(new SimpleInstruction(PUSHPRIVATEXPRESSION));
|
|
}
|
|
if (adv.nodeName == LineNode && adv.nodes.size() == 2) {
|
|
|
|
GenNode(instructions, adv.nodes[0], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
GenNode(instructions, adv.nodes[1], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(new SimpleInstruction(LINEINFO));
|
|
} else if (adv.nodeName == NullCoalescingExpression &&
|
|
adv.nodes.size() == 2) {
|
|
uint32_t ifId = NewId();
|
|
std::string ifIdTrue = "__compGenTrue";
|
|
ifIdTrue.append(std::to_string(ifId));
|
|
GenNode(instructions, adv.nodes[0], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(
|
|
new JumpStyleInstruction(Instruction::JMPIFDEFINED, ifIdTrue));
|
|
GenNode(instructions, adv.nodes[1], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(new LabelInstruction(ifIdTrue));
|
|
|
|
} else if (adv.nodeName == ClassStatement && adv.nodes.size() >= 3 &&
|
|
std::holds_alternative<std::string>(adv.nodes[0])) {
|
|
CodeGenClass cls;
|
|
cls.documentation = GetString(std::get<std::string>(adv.nodes[0]));
|
|
GetFunctionName(cls.name, adv.nodes[1]);
|
|
GetFunctionName(cls.inherits, adv.nodes[2]);
|
|
for (size_t i = 3; i < adv.nodes.size(); i++) {
|
|
auto &node = adv.nodes[i];
|
|
if (std::holds_alternative<AdvancedSyntaxNode>(node)) {
|
|
auto &adv2 = std::get<AdvancedSyntaxNode>(node);
|
|
CodeGenClassEntry ent;
|
|
ent.type = 0;
|
|
if (adv2.nodes.size() >= 2 &&
|
|
std::holds_alternative<std::string>(adv2.nodes[0]) &&
|
|
std::holds_alternative<std::string>(adv2.nodes[1])) {
|
|
ent.documentation =
|
|
GetString(std::get<std::string>(adv2.nodes[0]));
|
|
std::string type = std::get<std::string>(adv2.nodes[1]);
|
|
if (type == "private")
|
|
ent.type = 0;
|
|
else if (type == "protected")
|
|
ent.type = 1;
|
|
else if (type == "public")
|
|
ent.type = 2;
|
|
else if (type == "static")
|
|
ent.type = 3;
|
|
}
|
|
|
|
if (adv2.nodeName == MethodStatement &&
|
|
adv2.nodes.size() == 4 &&
|
|
std::holds_alternative<AdvancedSyntaxNode>(
|
|
adv2.nodes[2])) {
|
|
|
|
// documentation,myTkn.text,nameAndArgs,closureData
|
|
size_t fnindex = this->chunks.size();
|
|
ent.closure = (uint32_t)fnindex;
|
|
this->chunks.resize(fnindex + 1);
|
|
auto &nameAndArgs =
|
|
std::get<AdvancedSyntaxNode>(adv2.nodes[2]);
|
|
if (nameAndArgs.nodeName == FunctionCallExpression &&
|
|
!nameAndArgs.nodes.empty() &&
|
|
std::holds_alternative<AdvancedSyntaxNode>(
|
|
nameAndArgs.nodes[0])) {
|
|
auto &getvar = std::get<AdvancedSyntaxNode>(
|
|
nameAndArgs.nodes[0]);
|
|
if (getvar.nodeName == GetVariableExpression &&
|
|
getvar.nodes.size() == 1 &&
|
|
std::holds_alternative<std::string>(
|
|
getvar.nodes[0])) {
|
|
|
|
ent.name = GetString(
|
|
std::get<std::string>(getvar.nodes[0]));
|
|
if (nameAndArgs.nodes.size() > 1) {
|
|
GetFunctionArgs(ent.arguments,
|
|
nameAndArgs.nodes[1]);
|
|
}
|
|
} else
|
|
continue;
|
|
}
|
|
|
|
std::vector<ByteCodeInstruction *> fnInstructions;
|
|
|
|
GenNode(fnInstructions, adv2.nodes[3], 0, -1, -1, -1,
|
|
-1);
|
|
|
|
this->chunks[fnindex] =
|
|
std::pair<std::vector<uint32_t>,
|
|
std::vector<ByteCodeInstruction *>>(
|
|
ent.arguments, fnInstructions);
|
|
} else if (adv2.nodeName == AbstractMethodStatement &&
|
|
adv2.nodes.size() == 3 &&
|
|
std::holds_alternative<AdvancedSyntaxNode>(
|
|
adv2.nodes[2])) {
|
|
ent.closure = 0;
|
|
ent.type |= 0b00001000;
|
|
// documentation,myTkn.text,nameAndArgs
|
|
auto &nameAndArgs =
|
|
std::get<AdvancedSyntaxNode>(adv2.nodes[2]);
|
|
if (nameAndArgs.nodeName == FunctionCallExpression &&
|
|
!nameAndArgs.nodes.empty() &&
|
|
std::holds_alternative<AdvancedSyntaxNode>(
|
|
nameAndArgs.nodes[0])) {
|
|
auto &getvar = std::get<AdvancedSyntaxNode>(
|
|
nameAndArgs.nodes[0]);
|
|
if (getvar.nodeName == GetVariableExpression &&
|
|
getvar.nodes.size() == 1 &&
|
|
std::holds_alternative<std::string>(
|
|
getvar.nodes[0])) {
|
|
ent.name = GetString(
|
|
std::get<std::string>(getvar.nodes[0]));
|
|
if (nameAndArgs.nodes.size() > 1) {
|
|
GetFunctionArgs(ent.arguments,
|
|
nameAndArgs.nodes[1]);
|
|
}
|
|
} else
|
|
continue;
|
|
}
|
|
|
|
} else if (adv2.nodeName == FieldStatement &&
|
|
adv2.nodes.size() == 3 &&
|
|
std::holds_alternative<AdvancedSyntaxNode>(
|
|
adv2.nodes[2])) {
|
|
auto &setter =
|
|
std::get<AdvancedSyntaxNode>(adv2.nodes[2]);
|
|
if (setter.nodeName == GetVariableExpression &&
|
|
setter.nodes.size() == 1 &&
|
|
std::holds_alternative<std::string>(
|
|
setter.nodes[0])) {
|
|
ent.closure = 0;
|
|
ent.type |= 0b00001100;
|
|
|
|
ent.name = GetString(
|
|
std::get<std::string>(setter.nodes[0]));
|
|
|
|
} else if (setter.nodeName == AssignExpression &&
|
|
setter.nodes.size() == 2 &&
|
|
std::holds_alternative<AdvancedSyntaxNode>(
|
|
setter.nodes[0])) {
|
|
auto &getvar =
|
|
std::get<AdvancedSyntaxNode>(setter.nodes[0]);
|
|
if (getvar.nodeName == GetVariableExpression &&
|
|
getvar.nodes.size() == 1 &&
|
|
std::holds_alternative<std::string>(
|
|
getvar.nodes[0])) {
|
|
ent.type |= 0b00000100;
|
|
ent.name = GetString(
|
|
std::get<std::string>(getvar.nodes[0]));
|
|
size_t fnindex = this->chunks.size();
|
|
ent.closure = (uint32_t)fnindex;
|
|
ent.arguments = {};
|
|
|
|
this->chunks.resize(fnindex + 1);
|
|
|
|
std::vector<ByteCodeInstruction *>
|
|
fnInstructions;
|
|
|
|
GenNode(fnInstructions,
|
|
AdvancedSyntaxNode::Create(
|
|
ReturnStatement, false,
|
|
{setter.nodes[1]}),
|
|
0, -1, -1, -1, -1);
|
|
|
|
this->chunks[fnindex] = std::pair<
|
|
std::vector<uint32_t>,
|
|
std::vector<ByteCodeInstruction *>>(
|
|
{}, fnInstructions);
|
|
} else
|
|
continue;
|
|
} else
|
|
continue;
|
|
}
|
|
cls.entries.push_back(ent);
|
|
}
|
|
}
|
|
classes.push_back(cls);
|
|
} else if (adv.nodeName == RelativePathExpression) {
|
|
instructions.push_back(
|
|
new SimpleInstruction(Instruction::PUSHRELATIVEPATH));
|
|
} else if (adv.nodeName == RootPathExpression) {
|
|
instructions.push_back(
|
|
new SimpleInstruction(Instruction::PUSHROOTPATH));
|
|
} else if (adv.nodeName == SwitchStatement && adv.nodes.size() == 2) {
|
|
// THIS CODE WORKED FIRST TRY, I DON'T SEE THAT EVERY DAY, PRAISE
|
|
// GOD!!!!!!!
|
|
auto expr = adv.nodes[0];
|
|
|
|
std::vector<SyntaxNode> nodes_before;
|
|
|
|
SyntaxNode currentCase = nullptr;
|
|
std::vector<SyntaxNode> currentNodes;
|
|
std::string defaultJmp = {};
|
|
|
|
std::vector<std::pair<std::pair<std::string, AdvancedSyntaxNode>,
|
|
std::vector<SyntaxNode>>>
|
|
snodes;
|
|
|
|
if (std::holds_alternative<AdvancedSyntaxNode>(adv.nodes[1])) {
|
|
auto body = std::get<AdvancedSyntaxNode>(adv.nodes[1]);
|
|
if (body.nodeName == ScopeNode) {
|
|
for (auto item : body.nodes) {
|
|
if (std::holds_alternative<AdvancedSyntaxNode>(item)) {
|
|
auto no = std::get<AdvancedSyntaxNode>(item);
|
|
if (no.nodeName == CaseStatement ||
|
|
no.nodeName == DefaultStatement) {
|
|
if (std::holds_alternative<AdvancedSyntaxNode>(
|
|
currentCase)) {
|
|
|
|
uint32_t jmpId = NewId();
|
|
std::string jmpIdStr = "__compGenJmp";
|
|
jmpIdStr.append(std::to_string(jmpId));
|
|
snodes.push_back(
|
|
std::pair<std::pair<std::string,
|
|
AdvancedSyntaxNode>,
|
|
std::vector<SyntaxNode>>(
|
|
std::pair<std::string,
|
|
AdvancedSyntaxNode>(
|
|
jmpIdStr,
|
|
std::get<AdvancedSyntaxNode>(
|
|
currentCase)),
|
|
currentNodes));
|
|
currentNodes = {};
|
|
}
|
|
currentCase = no;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (std::holds_alternative<AdvancedSyntaxNode>(
|
|
currentCase)) {
|
|
currentNodes.push_back(item);
|
|
} else {
|
|
nodes_before.push_back(item);
|
|
}
|
|
}
|
|
if (std::holds_alternative<AdvancedSyntaxNode>(
|
|
currentCase)) {
|
|
|
|
uint32_t jmpId = NewId();
|
|
std::string jmpIdStr = "__compGenJmp";
|
|
jmpIdStr.append(std::to_string(jmpId));
|
|
snodes.push_back(
|
|
std::pair<
|
|
std::pair<std::string, AdvancedSyntaxNode>,
|
|
std::vector<SyntaxNode>>(
|
|
std::pair<std::string, AdvancedSyntaxNode>(
|
|
jmpIdStr,
|
|
std::get<AdvancedSyntaxNode>(currentCase)),
|
|
currentNodes));
|
|
currentNodes = {};
|
|
}
|
|
|
|
uint32_t endId = NewId();
|
|
std::string endIdStr = "__compGenBrk";
|
|
endIdStr.append(std::to_string(endId));
|
|
for (auto item : nodes_before) {
|
|
GenNode(instructions, item, scope, contscope, brkscope,
|
|
contI, brkI);
|
|
}
|
|
|
|
for (auto item : snodes) {
|
|
if (item.first.second.nodeName == CaseStatement) {
|
|
auto eq = AdvancedSyntaxNode::Create(
|
|
EqualsExpression, true,
|
|
{item.first.second.nodes[0], adv.nodes[0]});
|
|
GenNode(instructions, eq, scope, contscope,
|
|
brkscope, contI, brkI);
|
|
instructions.push_back(new JumpStyleInstruction(
|
|
JMPC, item.first.first));
|
|
}
|
|
if (item.first.second.nodeName == DefaultStatement) {
|
|
if (!defaultJmp.empty())
|
|
std::cout << "ERROR: multiple default in "
|
|
"switch statement will cause "
|
|
"undefined behaviour, this is not "
|
|
"an exception due to not allowing "
|
|
"exceptions in codegen stage (the "
|
|
"compilation shouldn't fail)"
|
|
<< std::endl;
|
|
defaultJmp = item.first.first;
|
|
}
|
|
}
|
|
|
|
if (defaultJmp.empty()) {
|
|
instructions.push_back(
|
|
new JumpStyleInstruction(JMP, endIdStr));
|
|
} else {
|
|
instructions.push_back(
|
|
new JumpStyleInstruction(JMP, defaultJmp));
|
|
}
|
|
|
|
for (auto item : snodes) {
|
|
instructions.push_back(
|
|
new LabelInstruction(item.first.first));
|
|
for (auto item2 : item.second) {
|
|
GenNode(instructions, item2, scope, contscope,
|
|
scope, contI, endId);
|
|
}
|
|
}
|
|
|
|
instructions.push_back(new LabelInstruction(endIdStr));
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
if (adv.nodeName == TernaryExpression && adv.nodes.size() == 3) {
|
|
uint32_t ifId = NewId();
|
|
std::string ifIdTrue = "__compGenTrue";
|
|
ifIdTrue.append(std::to_string(ifId));
|
|
std::string ifIdEnd = "__compGenEnd";
|
|
ifIdEnd.append(std::to_string(ifId));
|
|
|
|
GenNode(instructions, adv.nodes[0], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(new JumpStyleInstruction(JMPC, ifIdTrue));
|
|
if (!std::holds_alternative<std::nullptr_t>(adv.nodes[2])) {
|
|
GenNode(instructions, adv.nodes[2], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
}
|
|
instructions.push_back(new JumpStyleInstruction(JMP, ifIdEnd));
|
|
instructions.push_back(new LabelInstruction(ifIdTrue));
|
|
if (!std::holds_alternative<std::nullptr_t>(adv.nodes[1])) {
|
|
GenNode(instructions, adv.nodes[1], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
}
|
|
instructions.push_back(new LabelInstruction(ifIdEnd));
|
|
|
|
} else if (adv.nodeName == CompoundAssignExpression &&
|
|
adv.nodes.size() == 1 &&
|
|
std::holds_alternative<AdvancedSyntaxNode>(adv.nodes[0])) {
|
|
auto data = std::get<AdvancedSyntaxNode>(adv.nodes[0]);
|
|
if (data.nodes.size() == 2) {
|
|
auto d = AdvancedSyntaxNode::Create(AssignExpression, true,
|
|
{data.nodes[0], data});
|
|
GenNode(instructions, d, scope, contscope, brkscope, contI,
|
|
brkI);
|
|
}
|
|
} else if (adv.nodeName == PrefixIncrementExpression &&
|
|
adv.nodes.size() == 1) {
|
|
GenNode(instructions,
|
|
AdvancedSyntaxNode::Create(
|
|
CompoundAssignExpression, true,
|
|
{AdvancedSyntaxNode::Create(
|
|
AddExpression, true, {adv.nodes[0], (int64_t)1})}),
|
|
scope, contscope, brkscope, contI, brkI);
|
|
} else if (adv.nodeName == PrefixDecrementExpression &&
|
|
adv.nodes.size() == 1) {
|
|
GenNode(instructions,
|
|
AdvancedSyntaxNode::Create(
|
|
CompoundAssignExpression, true,
|
|
{AdvancedSyntaxNode::Create(
|
|
SubExpression, true, {adv.nodes[0], (int64_t)1})}),
|
|
scope, contscope, brkscope, contI, brkI);
|
|
} else if (adv.nodeName == PostfixIncrementExpression &&
|
|
adv.nodes.size() == 1) {
|
|
GenNode(instructions, adv.nodes[0], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
GenNode(instructions,
|
|
AdvancedSyntaxNode::Create(
|
|
CompoundAssignExpression, true,
|
|
{AdvancedSyntaxNode::Create(
|
|
AddExpression, true, {adv.nodes[0], (int64_t)1})}),
|
|
scope, contscope, brkscope, contI, brkI);
|
|
instructions.push_back(new SimpleInstruction(POP));
|
|
} else if (adv.nodeName == PostfixDecrementExpression &&
|
|
adv.nodes.size() == 1) {
|
|
GenNode(instructions, adv.nodes[0], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
GenNode(instructions,
|
|
AdvancedSyntaxNode::Create(
|
|
CompoundAssignExpression, true,
|
|
{AdvancedSyntaxNode::Create(
|
|
SubExpression, true, {adv.nodes[0], (int64_t)1})}),
|
|
scope, contscope, brkscope, contI, brkI);
|
|
instructions.push_back(new SimpleInstruction(POP));
|
|
} else if (adv.nodeName == LogicalOrExpression &&
|
|
adv.nodes.size() == 2) {
|
|
auto data = AdvancedSyntaxNode::Create(
|
|
TernaryExpression, true,
|
|
{adv.nodes[0], true,
|
|
AdvancedSyntaxNode::Create(TernaryExpression, true,
|
|
{adv.nodes[1], true, false})});
|
|
GenNode(instructions, data, scope, contscope, brkscope, contI,
|
|
brkI);
|
|
} else if (adv.nodeName == LogicalAndExpression &&
|
|
adv.nodes.size() == 2) {
|
|
auto data = AdvancedSyntaxNode::Create(
|
|
TernaryExpression, true,
|
|
{adv.nodes[0],
|
|
AdvancedSyntaxNode::Create(TernaryExpression, true,
|
|
{adv.nodes[1], true, false}),
|
|
false});
|
|
GenNode(instructions, data, scope, contscope, brkscope, contI,
|
|
brkI);
|
|
} else if (adv.nodeName == EachStatement && adv.nodes.size() == 3) {
|
|
auto item = adv.nodes[0];
|
|
auto list = adv.nodes[1];
|
|
auto body = adv.nodes[2];
|
|
|
|
uint32_t compGenId = NewId();
|
|
std::string compGenIttr = "__compGenIttr";
|
|
compGenIttr.append(std::to_string(compGenId));
|
|
|
|
auto each = AdvancedSyntaxNode::Create(
|
|
NodeList, false,
|
|
{AdvancedSyntaxNode::Create(
|
|
AssignExpression, true,
|
|
{AdvancedSyntaxNode::Create(DeclareExpression, true,
|
|
{compGenIttr}),
|
|
AdvancedSyntaxNode::Create(
|
|
FunctionCallExpression, true,
|
|
{AdvancedSyntaxNode::Create(
|
|
GetFieldExpression, true,
|
|
{list, "GetEnumerator"})})}),
|
|
AdvancedSyntaxNode::Create(
|
|
DeferStatement, false,
|
|
{AdvancedSyntaxNode::Create(
|
|
FunctionCallExpression, true,
|
|
{AdvancedSyntaxNode::Create(
|
|
GetFieldExpression, true,
|
|
{AdvancedSyntaxNode::Create(GetVariableExpression,
|
|
true, {compGenIttr}),
|
|
"Dispose"})})}),
|
|
AdvancedSyntaxNode::Create(
|
|
WhileStatement, false,
|
|
{AdvancedSyntaxNode::Create(
|
|
FunctionCallExpression, true,
|
|
{
|
|
AdvancedSyntaxNode::Create(
|
|
GetFieldExpression, true,
|
|
{AdvancedSyntaxNode::Create(
|
|
GetVariableExpression, true,
|
|
{compGenIttr}),
|
|
"MoveNext"}),
|
|
}),
|
|
AdvancedSyntaxNode::Create(
|
|
NodeList, false,
|
|
{AdvancedSyntaxNode::Create(
|
|
AssignExpression, true,
|
|
{item, AdvancedSyntaxNode::Create(
|
|
GetFieldExpression, true,
|
|
{AdvancedSyntaxNode::Create(
|
|
GetVariableExpression, true,
|
|
{compGenIttr}),
|
|
"Current"})}),
|
|
body})})});
|
|
GenNode(instructions, each, scope, contscope, brkscope, contI,
|
|
brkI);
|
|
|
|
} else if (adv.nodeName == ArrayExpression) {
|
|
instructions.push_back(new SimpleInstruction(CREATEARRAY));
|
|
std::vector<SyntaxNode> itms;
|
|
if (adv.nodes.size() > 0)
|
|
|
|
GetFunctionArgs(itms, adv.nodes[0]);
|
|
for (auto item : itms) {
|
|
GenNode(instructions, item, scope, contscope, brkscope, contI,
|
|
brkI);
|
|
instructions.push_back(new SimpleInstruction(APPENDLIST));
|
|
}
|
|
} else if (adv.nodeName == DictionaryExpression) {
|
|
instructions.push_back(new SimpleInstruction(CREATEDICTIONARY));
|
|
std::vector<SyntaxNode> itms;
|
|
if (adv.nodes.size() > 0)
|
|
GetFunctionArgs(itms, adv.nodes[0]);
|
|
for (auto item : itms) {
|
|
if (std::holds_alternative<AdvancedSyntaxNode>(item)) {
|
|
auto tkn = std::get<AdvancedSyntaxNode>(item);
|
|
if (tkn.nodeName == GetVariableExpression &&
|
|
!tkn.nodes.empty()) {
|
|
GenNode(instructions, tkn.nodes[0], scope, contscope,
|
|
brkscope, contI, brkI);
|
|
GenNode(instructions, item, scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(
|
|
new SimpleInstruction(APPENDDICT));
|
|
} else if (tkn.nodeName == AssignExpression &&
|
|
tkn.nodes.size() == 2 &&
|
|
std::holds_alternative<AdvancedSyntaxNode>(
|
|
tkn.nodes[0])) {
|
|
auto myTn = std::get<AdvancedSyntaxNode>(tkn.nodes[0]);
|
|
if (myTn.nodeName == GetVariableExpression &&
|
|
!myTn.nodes.empty()) {
|
|
GenNode(instructions, myTn.nodes[0], scope,
|
|
contscope, brkscope, contI, brkI);
|
|
GenNode(instructions, tkn.nodes[1], scope,
|
|
contscope, brkscope, contI, brkI);
|
|
instructions.push_back(
|
|
new SimpleInstruction(APPENDDICT));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else if (adv.nodeName == FunctionCallExpression &&
|
|
adv.nodes.size() >= 1 &&
|
|
std::holds_alternative<AdvancedSyntaxNode>(adv.nodes[0])) {
|
|
auto v = std::get<AdvancedSyntaxNode>(adv.nodes[0]);
|
|
if (v.nodeName == GetFieldExpression && v.nodes.size() == 2) {
|
|
GenNode(instructions, v.nodes[0], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
GenNode(instructions, v.nodes[1], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
if (adv.nodes.size() == 2) {
|
|
std::vector<SyntaxNode> nodes;
|
|
GetFunctionArgs(nodes, adv.nodes[1]);
|
|
for (auto item : nodes)
|
|
GenNode(instructions, item, scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(
|
|
new LongInstruction((int64_t)nodes.size()));
|
|
} else {
|
|
instructions.push_back(new LongInstruction(0));
|
|
}
|
|
instructions.push_back(new SimpleInstruction(CALLMETHOD));
|
|
} else if (v.nodeName != GetFieldExpression) {
|
|
GenNode(instructions, adv.nodes[0], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
if (adv.nodes.size() == 2) {
|
|
std::vector<SyntaxNode> nodes;
|
|
GetFunctionArgs(nodes, adv.nodes[1]);
|
|
for (auto item : nodes)
|
|
GenNode(instructions, item, scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(
|
|
new LongInstruction((int64_t)nodes.size()));
|
|
} else {
|
|
instructions.push_back(new LongInstruction(0));
|
|
}
|
|
instructions.push_back(new SimpleInstruction(CALLFUNCTION));
|
|
}
|
|
} else if (adv.nodeName == IfStatement && adv.nodes.size() == 3) {
|
|
uint32_t ifId = NewId();
|
|
std::string ifIdTrue = "__compGenTrue";
|
|
ifIdTrue.append(std::to_string(ifId));
|
|
std::string ifIdEnd = "__compGenEnd";
|
|
ifIdEnd.append(std::to_string(ifId));
|
|
|
|
GenNode(instructions, adv.nodes[0], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(new JumpStyleInstruction(JMPC, ifIdTrue));
|
|
if (!std::holds_alternative<std::nullptr_t>(adv.nodes[2])) {
|
|
GenNode(instructions, adv.nodes[2], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
GenPop(instructions, adv.nodes[2]);
|
|
}
|
|
instructions.push_back(new JumpStyleInstruction(JMP, ifIdEnd));
|
|
instructions.push_back(new LabelInstruction(ifIdTrue));
|
|
if (!std::holds_alternative<std::nullptr_t>(adv.nodes[1])) {
|
|
GenNode(instructions, adv.nodes[1], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
GenPop(instructions, adv.nodes[1]);
|
|
}
|
|
instructions.push_back(new LabelInstruction(ifIdEnd));
|
|
|
|
} else if (adv.nodeName == UsingStatement && adv.nodes.size() == 2) {
|
|
// using(EXPRESSION) {}
|
|
// using(EXPRESSION) STATEMENT;
|
|
|
|
//{ __compGen = EXPRESSION; defer { __compGen.Dispose(); }
|
|
//{}(unrolled) OR STATEMENT; }
|
|
|
|
if (std::holds_alternative<AdvancedSyntaxNode>(adv.nodes[1])) {
|
|
auto asn2 = std::get<AdvancedSyntaxNode>(adv.nodes[1]);
|
|
if (asn2.nodeName == ScopeNode) {
|
|
scope++;
|
|
instructions.push_back(new SimpleInstruction(SCOPEBEGIN));
|
|
|
|
uint32_t exprId = NewId();
|
|
std::string exprStr = "__compGenUsing";
|
|
exprStr.append(std::to_string(exprId));
|
|
|
|
auto _assign = AdvancedSyntaxNode::Create(
|
|
AssignExpression, true,
|
|
{AdvancedSyntaxNode::Create(DeclareExpression, true,
|
|
{exprStr}),
|
|
adv.nodes[0]});
|
|
|
|
GenNode(instructions, _assign, scope, contscope, brkscope,
|
|
contI, brkI);
|
|
GenPop(instructions, _assign);
|
|
|
|
auto _defer = AdvancedSyntaxNode::Create(
|
|
DeferStatement, false,
|
|
{AdvancedSyntaxNode::Create(
|
|
ReturnStatement, false,
|
|
{AdvancedSyntaxNode::Create(
|
|
FunctionCallExpression, true,
|
|
{AdvancedSyntaxNode::Create(
|
|
GetFieldExpression, true,
|
|
{AdvancedSyntaxNode::Create(
|
|
GetVariableExpression, true,
|
|
{exprStr}),
|
|
"Dispose"})})})});
|
|
|
|
GenNode(instructions, _defer, scope, contscope, brkscope,
|
|
contI, brkI);
|
|
|
|
for (size_t i = 0; i < asn2.nodes.size(); i++) {
|
|
GenNode(instructions, asn2.nodes[i], scope, contscope,
|
|
brkscope, contI, brkI);
|
|
if (!asn2.isExpression || i < asn2.nodes.size() - 1)
|
|
GenPop(instructions, asn2.nodes[i]);
|
|
}
|
|
instructions.push_back(new SimpleInstruction(SCOPEEND));
|
|
scope--;
|
|
return;
|
|
}
|
|
}
|
|
|
|
{
|
|
scope++;
|
|
instructions.push_back(new SimpleInstruction(SCOPEBEGIN));
|
|
|
|
uint32_t exprId = NewId();
|
|
std::string exprStr = "__compGenUsing";
|
|
exprStr.append(std::to_string(exprId));
|
|
|
|
auto _assign = AdvancedSyntaxNode::Create(
|
|
AssignExpression, true,
|
|
{AdvancedSyntaxNode::Create(DeclareExpression, true,
|
|
{exprStr}),
|
|
adv.nodes[0]});
|
|
|
|
GenNode(instructions, _assign, scope, contscope, brkscope,
|
|
contI, brkI);
|
|
GenPop(instructions, _assign);
|
|
|
|
auto _defer = AdvancedSyntaxNode::Create(
|
|
DeferStatement, false,
|
|
{AdvancedSyntaxNode::Create(
|
|
ReturnStatement, false,
|
|
{AdvancedSyntaxNode::Create(
|
|
FunctionCallExpression, true,
|
|
{AdvancedSyntaxNode::Create(
|
|
GetFieldExpression, true,
|
|
{AdvancedSyntaxNode::Create(
|
|
GetVariableExpression, true, {exprStr}),
|
|
"Dispose"})})})});
|
|
|
|
GenNode(instructions, _defer, scope, contscope, brkscope, contI,
|
|
brkI);
|
|
|
|
GenNode(instructions, adv.nodes[1], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
if (!adv.isExpression)
|
|
GenPop(instructions, adv.nodes[1]);
|
|
|
|
instructions.push_back(new SimpleInstruction(SCOPEEND));
|
|
scope--;
|
|
}
|
|
} else if (adv.nodeName == WhileStatement && adv.nodes.size() == 2) {
|
|
auto old_contI = contI;
|
|
auto old_brkI = brkI;
|
|
auto old_contscope = contscope;
|
|
auto old_brkscope = brkscope;
|
|
|
|
contscope = scope;
|
|
brkscope = scope;
|
|
|
|
uint32_t whileId = NewId();
|
|
std::string whileIdCont = "__compGenCont";
|
|
whileIdCont.append(std::to_string(whileId));
|
|
std::string whileIdBrk = "__compGenBrk";
|
|
whileIdBrk.append(std::to_string(whileId));
|
|
|
|
contI = whileId;
|
|
brkI = whileId;
|
|
|
|
instructions.push_back(new LabelInstruction(whileIdCont));
|
|
GenNode(instructions, adv.nodes[0], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(new SimpleInstruction(NOT));
|
|
instructions.push_back(new JumpStyleInstruction(JMPC, whileIdBrk));
|
|
|
|
if (!std::holds_alternative<std::nullptr_t>(adv.nodes[1])) {
|
|
GenNode(instructions, adv.nodes[1], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
GenPop(instructions, adv.nodes[1]);
|
|
}
|
|
|
|
instructions.push_back(new JumpStyleInstruction(JMP, whileIdCont));
|
|
instructions.push_back(new LabelInstruction(whileIdBrk));
|
|
|
|
contI = old_contI;
|
|
brkI = old_brkI;
|
|
contscope = old_contscope;
|
|
brkscope = old_brkscope;
|
|
|
|
} else if (adv.nodeName == DoStatement && adv.nodes.size() == 2) {
|
|
auto old_contI = contI;
|
|
auto old_brkI = brkI;
|
|
auto old_contscope = contscope;
|
|
auto old_brkscope = brkscope;
|
|
|
|
contscope = scope;
|
|
brkscope = scope;
|
|
|
|
uint32_t doId = NewId();
|
|
std::string doIdCont = "__compGenCont";
|
|
doIdCont.append(std::to_string(doId));
|
|
std::string doIdBrk = "__compGenBrk";
|
|
doIdBrk.append(std::to_string(doId));
|
|
std::string doIdStart = "__compGenStart";
|
|
doIdStart.append(std::to_string(doId));
|
|
|
|
contI = doId;
|
|
brkI = doId;
|
|
|
|
instructions.push_back(new LabelInstruction(doIdStart));
|
|
|
|
if (!std::holds_alternative<std::nullptr_t>(adv.nodes[1])) {
|
|
GenNode(instructions, adv.nodes[1], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
GenPop(instructions, adv.nodes[1]);
|
|
}
|
|
instructions.push_back(new LabelInstruction(doIdCont));
|
|
GenNode(instructions, adv.nodes[0], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
|
|
instructions.push_back(new JumpStyleInstruction(JMPC, doIdStart));
|
|
instructions.push_back(new LabelInstruction(doIdBrk));
|
|
|
|
contI = old_contI;
|
|
brkI = old_brkI;
|
|
contscope = old_contscope;
|
|
brkscope = old_brkscope;
|
|
|
|
} else if (adv.nodeName == ForStatement && adv.nodes.size() == 4) {
|
|
if (!std::holds_alternative<std::nullptr_t>(adv.nodes[0])) {
|
|
GenNode(instructions, adv.nodes[0], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
GenPop(instructions, adv.nodes[0]);
|
|
}
|
|
auto old_contI = contI;
|
|
auto old_brkI = brkI;
|
|
auto old_contscope = contscope;
|
|
auto old_brkscope = brkscope;
|
|
|
|
contscope = scope;
|
|
brkscope = scope;
|
|
|
|
uint32_t doId = NewId();
|
|
std::string doIdCont = "__compGenCont";
|
|
doIdCont.append(std::to_string(doId));
|
|
std::string doIdBrk = "__compGenBrk";
|
|
doIdBrk.append(std::to_string(doId));
|
|
std::string doIdStart = "__compGenStart";
|
|
doIdStart.append(std::to_string(doId));
|
|
std::string doIdStart2 = "__compGenCond";
|
|
doIdStart2.append(std::to_string(doId));
|
|
|
|
contI = doId;
|
|
brkI = doId;
|
|
|
|
instructions.push_back(new JumpStyleInstruction(JMP, doIdStart2));
|
|
instructions.push_back(new LabelInstruction(doIdStart));
|
|
if (!std::holds_alternative<std::nullptr_t>(adv.nodes[3])) {
|
|
GenNode(instructions, adv.nodes[3], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
GenPop(instructions, adv.nodes[3]);
|
|
}
|
|
|
|
instructions.push_back(new LabelInstruction(doIdCont));
|
|
if (!std::holds_alternative<std::nullptr_t>(adv.nodes[2])) {
|
|
GenNode(instructions, adv.nodes[2], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
GenPop(instructions, adv.nodes[2]);
|
|
}
|
|
instructions.push_back(new LabelInstruction(doIdStart2));
|
|
GenNode(instructions, adv.nodes[1], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(new JumpStyleInstruction(JMPC, doIdStart));
|
|
instructions.push_back(new LabelInstruction(doIdBrk));
|
|
contI = old_contI;
|
|
brkI = old_brkI;
|
|
contscope = old_contscope;
|
|
brkscope = old_brkscope;
|
|
} else if (adv.nodeName == CommaExpression && adv.nodes.size() == 2) {
|
|
GenNode(instructions, adv.nodes[0], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
GenPop(instructions, adv.nodes[0]);
|
|
GenNode(instructions, adv.nodes[1], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
|
|
} else if (adv.nodeName == ContinueStatement) {
|
|
if (contscope == -1) {
|
|
std::cout << "WARN: continue does nothing here\n";
|
|
} else if (contscope == -2) {
|
|
instructions.push_back(new SimpleInstruction(PUSHCONTINUE));
|
|
instructions.push_back(new SimpleInstruction(RET));
|
|
} else {
|
|
auto cont = scope - contscope;
|
|
if (cont > 0)
|
|
instructions.push_back(
|
|
new ScopeEndTimesInstruction((uint32_t)cont));
|
|
|
|
std::string myJmp = "__compGenCont";
|
|
myJmp.append(std::to_string(contI));
|
|
|
|
instructions.push_back(new JumpStyleInstruction(JMP, myJmp));
|
|
}
|
|
} else if (adv.nodeName == BreakStatement) {
|
|
if (brkscope == -1) {
|
|
std::cout << "WARN: break does nothing here\n";
|
|
} else if (brkscope == -2) {
|
|
instructions.push_back(new SimpleInstruction(PUSHBREAK));
|
|
instructions.push_back(new SimpleInstruction(RET));
|
|
} else {
|
|
auto _brk = scope - brkscope;
|
|
if (_brk > 0)
|
|
instructions.push_back(
|
|
new ScopeEndTimesInstruction((uint32_t)_brk));
|
|
|
|
std::string myJmp = "__compGenBrk";
|
|
myJmp.append(std::to_string(brkI));
|
|
|
|
instructions.push_back(new JumpStyleInstruction(JMP, myJmp));
|
|
}
|
|
} else if (adv.nodeName == GetVariableExpression &&
|
|
adv.nodes.size() == 1) {
|
|
GenNode(instructions, adv.nodes[0], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(new SimpleInstruction(GETVARIABLE));
|
|
} else if (adv.nodeName == GetFieldExpression &&
|
|
adv.nodes.size() == 2) {
|
|
|
|
GenNode(instructions, adv.nodes[0], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
GenNode(instructions, adv.nodes[1], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
|
|
instructions.push_back(new SimpleInstruction(GETFIELD));
|
|
|
|
} else if (adv.nodeName == GetArrayExpression &&
|
|
adv.nodes.size() == 2) {
|
|
SyntaxNode n = AdvancedSyntaxNode::Create(
|
|
FunctionCallExpression, true,
|
|
{AdvancedSyntaxNode::Create(GetFieldExpression, true,
|
|
{adv.nodes[0], "GetAt"}),
|
|
adv.nodes[1]});
|
|
GenNode(instructions, n, scope, contscope, brkscope, contI, brkI);
|
|
} else if (adv.nodeName == AssignExpression && adv.nodes.size() == 2 &&
|
|
std::holds_alternative<AdvancedSyntaxNode>(adv.nodes[0])) {
|
|
auto varNode = std::get<AdvancedSyntaxNode>(adv.nodes[0]);
|
|
|
|
if (varNode.nodeName == GetVariableExpression &&
|
|
varNode.nodes.size() == 1) {
|
|
GenNode(instructions, varNode.nodes[0], scope, contscope,
|
|
brkscope, contI, brkI);
|
|
GenNode(instructions, adv.nodes[1], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(new SimpleInstruction(SETVARIABLE));
|
|
} else if (varNode.nodeName == ArrayExpression &&
|
|
varNode.nodes.size() >= 1) {
|
|
|
|
auto vars = StringifyListOfVars(varNode.nodes[0]);
|
|
|
|
auto nArray =
|
|
AdvancedSyntaxNode::Create(ArrayExpression, true, {vars});
|
|
|
|
this->GenNode(instructions, nArray, scope, contscope, brkscope,
|
|
contI, brkI);
|
|
GenNode(instructions, adv.nodes[1], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(new SimpleInstruction(SETVARIABLE));
|
|
} else if (varNode.nodeName == DeclareExpression &&
|
|
varNode.nodes.size() == 1 &&
|
|
std::holds_alternative<std::string>(varNode.nodes[0])) {
|
|
GenNode(instructions, varNode.nodes[0], scope, contscope,
|
|
brkscope, contI, brkI);
|
|
GenNode(instructions, adv.nodes[1], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(new SimpleInstruction(DECLAREVARIABLE));
|
|
} else if (varNode.nodeName == DeclareExpression &&
|
|
varNode.nodes.size() == 1 &&
|
|
std::holds_alternative<AdvancedSyntaxNode>(
|
|
varNode.nodes[0])) {
|
|
auto adv2 = std::get<AdvancedSyntaxNode>(varNode.nodes[0]);
|
|
|
|
if (adv2.nodeName == ArrayExpression &&
|
|
adv2.nodes.size() == 1) {
|
|
|
|
auto vars = StringifyListOfVars(adv2.nodes[0]);
|
|
|
|
auto nArray = AdvancedSyntaxNode::Create(ArrayExpression,
|
|
true, {vars});
|
|
|
|
this->GenNode(instructions, nArray, scope, contscope,
|
|
brkscope, contI, brkI);
|
|
GenNode(instructions, adv.nodes[1], scope, contscope,
|
|
brkscope, contI, brkI);
|
|
instructions.push_back(
|
|
new SimpleInstruction(DECLAREVARIABLE));
|
|
}
|
|
} else if (varNode.nodeName == ConstExpression &&
|
|
varNode.nodes.size() == 1 &&
|
|
std::holds_alternative<std::string>(varNode.nodes[0])) {
|
|
GenNode(instructions, varNode.nodes[0], scope, contscope,
|
|
brkscope, contI, brkI);
|
|
GenNode(instructions, adv.nodes[1], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(
|
|
new SimpleInstruction(DECLARECONSTVARIABLE));
|
|
} else if (varNode.nodeName == ConstExpression &&
|
|
varNode.nodes.size() == 1 &&
|
|
std::holds_alternative<AdvancedSyntaxNode>(
|
|
varNode.nodes[0])) {
|
|
auto adv2 = std::get<AdvancedSyntaxNode>(varNode.nodes[0]);
|
|
|
|
if (adv2.nodeName == ArrayExpression &&
|
|
adv2.nodes.size() == 1) {
|
|
|
|
auto vars = StringifyListOfVars(adv2.nodes[0]);
|
|
|
|
auto nArray = AdvancedSyntaxNode::Create(ArrayExpression,
|
|
true, {vars});
|
|
|
|
this->GenNode(instructions, nArray, scope, contscope,
|
|
brkscope, contI, brkI);
|
|
GenNode(instructions, adv.nodes[1], scope, contscope,
|
|
brkscope, contI, brkI);
|
|
instructions.push_back(
|
|
new SimpleInstruction(DECLARECONSTVARIABLE));
|
|
}
|
|
} else if (varNode.nodeName == GetFieldExpression &&
|
|
varNode.nodes.size() == 2) {
|
|
GenNode(instructions, varNode.nodes[0], scope, contscope,
|
|
brkscope, contI, brkI);
|
|
|
|
GenNode(instructions, varNode.nodes[1], scope, contscope,
|
|
brkscope, contI, brkI);
|
|
GenNode(instructions, adv.nodes[1], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(new SimpleInstruction(SETFIELD));
|
|
} else if (varNode.nodeName == GetArrayExpression &&
|
|
varNode.nodes.size() == 2) {
|
|
SyntaxNode n = AdvancedSyntaxNode::Create(
|
|
FunctionCallExpression, true,
|
|
{AdvancedSyntaxNode::Create(GetFieldExpression, true,
|
|
{varNode.nodes[0], "SetAt"}),
|
|
AdvancedSyntaxNode::Create(
|
|
CommaExpression, true,
|
|
{varNode.nodes[1], adv.nodes[1]})});
|
|
GenNode(instructions, n, scope, contscope, brkscope, contI,
|
|
brkI);
|
|
}
|
|
} else if (adv.nodeName == BreakpointStatement &&
|
|
adv.nodes.size() == 5) {
|
|
instructions.push_back(new SimpleInstruction(CREATEDICTIONARY));
|
|
instructions.push_back(new StringInstruction(GetString("Data")));
|
|
GenNode(instructions, adv.nodes[0], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(new SimpleInstruction(APPENDDICT));
|
|
instructions.push_back(
|
|
new StringInstruction(GetString("Filename")));
|
|
GenNode(instructions, adv.nodes[1], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(new SimpleInstruction(APPENDDICT));
|
|
instructions.push_back(new StringInstruction(GetString("Line")));
|
|
GenNode(instructions, adv.nodes[2], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(new SimpleInstruction(APPENDDICT));
|
|
instructions.push_back(new StringInstruction(GetString("Column")));
|
|
GenNode(instructions, adv.nodes[3], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(new SimpleInstruction(APPENDDICT));
|
|
instructions.push_back(new StringInstruction(GetString("Offset")));
|
|
GenNode(instructions, adv.nodes[4], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(new SimpleInstruction(APPENDDICT));
|
|
instructions.push_back(new SimpleInstruction(BREAKPOINT));
|
|
} else if (adv.nodeName == ThrowStatement && adv.nodes.size() == 5) {
|
|
GenNode(instructions, adv.nodes[0], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(
|
|
new StringInstruction(GetString("Filename")));
|
|
GenNode(instructions, adv.nodes[1], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(new SimpleInstruction(APPENDDICT));
|
|
instructions.push_back(new StringInstruction(GetString("Line")));
|
|
GenNode(instructions, adv.nodes[2], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(new SimpleInstruction(APPENDDICT));
|
|
instructions.push_back(new StringInstruction(GetString("Column")));
|
|
GenNode(instructions, adv.nodes[3], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(new SimpleInstruction(APPENDDICT));
|
|
instructions.push_back(new StringInstruction(GetString("Offset")));
|
|
GenNode(instructions, adv.nodes[4], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(new SimpleInstruction(APPENDDICT));
|
|
instructions.push_back(new SimpleInstruction(THROW));
|
|
} else if (adv.nodeName == ReturnStatement && adv.nodes.size() == 1) {
|
|
GenNode(instructions, adv.nodes[0], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(new SimpleInstruction(RET));
|
|
} else if (adv.nodeName == YieldStatement && adv.nodes.size() == 1) {
|
|
GenNode(instructions, adv.nodes[0], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
instructions.push_back(new SimpleInstruction(YIELD));
|
|
} else if (adv.nodeName == ParenthesesExpression &&
|
|
adv.nodes.size() == 1) {
|
|
GenNode(instructions, adv.nodes[0], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
} else if (adv.nodeName == EmbedExpression && adv.nodes.size() == 1 &&
|
|
std::holds_alternative<std::string>(adv.nodes[0])) {
|
|
std::string filename = std::get<std::string>(adv.nodes[0]);
|
|
instructions.push_back(new EmbedInstruction(
|
|
GetResource(std::make_shared<ResourceFile>(filename))));
|
|
|
|
} else if (adv.nodeName == MetadataStatement && adv.nodes.size() == 2 &&
|
|
std::holds_alternative<std::string>(adv.nodes[0])) {
|
|
auto &name = std::get<std::string>(adv.nodes[0]);
|
|
|
|
auto &metabytes = this->meta.emplace_back();
|
|
metabytes.resize(4);
|
|
BitConverter::FromUint32BE(metabytes[0], GetString(name));
|
|
|
|
WriteMetadataObject(metabytes, adv.nodes[1]);
|
|
} else if (adv.nodeName == EmbedStreamExpression &&
|
|
adv.nodes.size() == 1 &&
|
|
std::holds_alternative<std::string>(adv.nodes[0])) {
|
|
std::string filename = std::get<std::string>(adv.nodes[0]);
|
|
instructions.push_back(new EmbedStreamInstruction(
|
|
GetResource(std::make_shared<ResourceFile>(filename))));
|
|
|
|
} else if (adv.nodeName == EmbedDirectoryExpression &&
|
|
adv.nodes.size() == 1 &&
|
|
std::holds_alternative<std::string>(adv.nodes[0])) {
|
|
std::string filename = std::get<std::string>(adv.nodes[0]);
|
|
std::function<void(Tesses::Framework::Filesystem::VFSPath path)>
|
|
embedDir;
|
|
embedDir =
|
|
[&](Tesses::Framework::Filesystem::VFSPath path) -> void {
|
|
instructions.push_back(new SimpleInstruction(CREATEDICTIONARY));
|
|
|
|
if (embedFS != nullptr && embedFS->DirectoryExists(path))
|
|
for (auto &item : embedFS->EnumeratePaths(path)) {
|
|
GenNode(instructions, item.GetFileName(), scope,
|
|
contscope, brkscope, contI, brkI);
|
|
if (embedFS->DirectoryExists(item)) {
|
|
embedDir(item);
|
|
} else if (embedFS->RegularFileExists(item)) {
|
|
auto ce = AdvancedSyntaxNode::Create(
|
|
ClosureExpression, true,
|
|
{AdvancedSyntaxNode::Create(
|
|
ParenthesesExpression, true, {}),
|
|
AdvancedSyntaxNode::Create(
|
|
ReturnStatement, false,
|
|
{AdvancedSyntaxNode::Create(
|
|
EmbedStreamExpression, true,
|
|
{item.ToString()})})});
|
|
GenNode(instructions, ce, scope, contscope,
|
|
brkscope, contI, brkI);
|
|
} else {
|
|
instructions.push_back(
|
|
new SimpleInstruction(PUSHUNDEFINED));
|
|
}
|
|
|
|
instructions.push_back(
|
|
new SimpleInstruction(APPENDDICT));
|
|
}
|
|
};
|
|
embedDir(filename);
|
|
//
|
|
// instructions.push_back(new
|
|
// EmbedStreamInstruction(GetResource(std::make_shared<ResourceFile>(filename))));
|
|
instructions.push_back(new SimpleInstruction(PUSHRESOUURCEDIR));
|
|
} else if (adv.nodeName == HtmlRootExpression) {
|
|
scope++;
|
|
instructions.push_back(new SimpleInstruction(SCOPEBEGIN));
|
|
|
|
instructions.push_back(new StringInstruction(
|
|
GetString(std::get<std::string>(adv.nodes[0]))));
|
|
instructions.push_back(new StringInstruction(GetString("")));
|
|
instructions.push_back(new SimpleInstruction(DECLAREVARIABLE));
|
|
instructions.push_back(new SimpleInstruction(POP));
|
|
|
|
for (size_t i = 1; i < adv.nodes.size(); i++) {
|
|
GenNode(instructions, adv.nodes[i], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
GenPop(instructions, adv.nodes[i]);
|
|
}
|
|
|
|
instructions.push_back(new StringInstruction(
|
|
GetString(std::get<std::string>(adv.nodes[0]))));
|
|
instructions.push_back(new SimpleInstruction(GETVARIABLE));
|
|
instructions.push_back(new SimpleInstruction(SCOPEEND));
|
|
scope--;
|
|
} else if (adv.nodeName == ScopeNode) {
|
|
|
|
scope++;
|
|
instructions.push_back(new SimpleInstruction(SCOPEBEGIN));
|
|
for (size_t i = 0; i < adv.nodes.size(); i++) {
|
|
GenNode(instructions, adv.nodes[i], scope, contscope, brkscope,
|
|
contI, brkI);
|
|
if (!adv.isExpression || i < adv.nodes.size() - 1)
|
|
GenPop(instructions, adv.nodes[i]);
|
|
}
|
|
instructions.push_back(new SimpleInstruction(SCOPEEND));
|
|
scope--;
|
|
} else if (adv.nodeName == NodeList) {
|
|
|
|
for (auto item : adv.nodes) {
|
|
GenNode(instructions, item, scope, contscope, brkscope, contI,
|
|
brkI);
|
|
GenPop(instructions, item);
|
|
}
|
|
} else if (adv.nodeName == DeferStatement && adv.nodes.size() == 1) {
|
|
GenNode(instructions,
|
|
AdvancedSyntaxNode::Create(
|
|
ScopelessClosureExpression, true,
|
|
{AdvancedSyntaxNode::Create(ParenthesesExpression, true,
|
|
{}),
|
|
adv.nodes[0]}),
|
|
scope, contscope, brkscope, contI, brkI);
|
|
instructions.push_back(new SimpleInstruction(DEFER));
|
|
} else if (adv.nodeName == TryStatement && adv.nodes.size() == 4) {
|
|
// AdvancedSyntaxNode::Create(TryStatement, false,
|
|
// {tryBody,catchNode,catchEx, finally});
|
|
if (std::holds_alternative<AdvancedSyntaxNode>(adv.nodes[3])) {
|
|
GenNode(instructions,
|
|
AdvancedSyntaxNode::Create(DeferStatement, false,
|
|
{adv.nodes[3]}),
|
|
scope, contscope, brkscope, contI, brkI);
|
|
}
|
|
if (std::holds_alternative<AdvancedSyntaxNode>(adv.nodes[0]) &&
|
|
std::holds_alternative<AdvancedSyntaxNode>(adv.nodes[1]) &&
|
|
std::holds_alternative<AdvancedSyntaxNode>(adv.nodes[2])) {
|
|
GenNode(instructions,
|
|
AdvancedSyntaxNode::Create(
|
|
ScopelessClosureExpression, true,
|
|
{AdvancedSyntaxNode::Create(ParenthesesExpression,
|
|
true, {}),
|
|
adv.nodes[0]}),
|
|
scope, contscope == -1 ? -1 : -2,
|
|
brkscope == -1 ? -1 : -2, contI, brkI);
|
|
GenNode(instructions,
|
|
AdvancedSyntaxNode::Create(
|
|
ScopelessClosureExpression, true,
|
|
{AdvancedSyntaxNode::Create(ParenthesesExpression,
|
|
true, {adv.nodes[2]}),
|
|
adv.nodes[1]}),
|
|
scope, contscope == -1 ? -1 : -2,
|
|
brkscope == -1 ? -1 : -2, contI, brkI);
|
|
instructions.push_back(new SimpleInstruction(TRYCATCH));
|
|
uint32_t compGenId = NewId();
|
|
std::string compGenIttr = "__compGenRetThing";
|
|
compGenIttr.append(std::to_string(compGenId));
|
|
if (contscope != -1) {
|
|
instructions.push_back(new JumpStyleInstruction(
|
|
JMPIFCONTINUE, compGenIttr + "_cont"));
|
|
}
|
|
if (brkscope != -1) {
|
|
instructions.push_back(new JumpStyleInstruction(
|
|
JMPIFBREAK, compGenIttr + "_brk"));
|
|
}
|
|
instructions.push_back(
|
|
new JumpStyleInstruction(JMPUNDEFINED, compGenIttr));
|
|
instructions.push_back(new SimpleInstruction(RET));
|
|
if (contscope == -2) {
|
|
instructions.push_back(
|
|
new LabelInstruction(compGenIttr + "_cont"));
|
|
instructions.push_back(new SimpleInstruction(PUSHCONTINUE));
|
|
instructions.push_back(new SimpleInstruction(RET));
|
|
} else if (contscope != -1) {
|
|
instructions.push_back(
|
|
new LabelInstruction(compGenIttr + "_cont"));
|
|
auto cont = scope - contscope;
|
|
if (cont > 0)
|
|
instructions.push_back(
|
|
new ScopeEndTimesInstruction((uint32_t)cont));
|
|
|
|
std::string myJmp = "__compGenCont";
|
|
myJmp.append(std::to_string(contI));
|
|
|
|
instructions.push_back(
|
|
new JumpStyleInstruction(JMP, myJmp));
|
|
}
|
|
if (brkscope == -2) {
|
|
instructions.push_back(
|
|
new LabelInstruction(compGenIttr + "_brk"));
|
|
instructions.push_back(new SimpleInstruction(PUSHBREAK));
|
|
instructions.push_back(new SimpleInstruction(RET));
|
|
} else if (brkscope != -1) {
|
|
instructions.push_back(
|
|
new LabelInstruction(compGenIttr + "_brk"));
|
|
auto _brk = scope - brkscope;
|
|
if (_brk > 0)
|
|
instructions.push_back(
|
|
new ScopeEndTimesInstruction((uint32_t)_brk));
|
|
|
|
std::string myJmp = "__compGenBrk";
|
|
myJmp.append(std::to_string(brkI));
|
|
|
|
instructions.push_back(
|
|
new JumpStyleInstruction(JMP, myJmp));
|
|
}
|
|
|
|
instructions.push_back(new LabelInstruction(compGenIttr));
|
|
}
|
|
|
|
} else if (adv.nodeName == ScopelessClosureExpression &&
|
|
adv.nodes.size() == 2) {
|
|
//()=>{}
|
|
// Name => {}
|
|
//(a,b) => {}
|
|
// it has two args
|
|
std::vector<uint32_t> args;
|
|
GetFunctionArgs(args, adv.nodes[0]);
|
|
|
|
std::vector<ByteCodeInstruction *> fnInstructions;
|
|
size_t fnindex = this->chunks.size();
|
|
this->chunks.resize(fnindex + 1);
|
|
|
|
auto body = adv.nodes[1];
|
|
|
|
if (std::holds_alternative<AdvancedSyntaxNode>(body)) {
|
|
auto res = std::get<AdvancedSyntaxNode>(body);
|
|
if (res.nodeName == ScopeNode) {
|
|
res.nodeName = NodeList;
|
|
}
|
|
body = res;
|
|
}
|
|
|
|
GenNode(fnInstructions, body, 0, contscope == -2 ? -2 : -1,
|
|
brkscope == -2 ? -2 : -1, -1, -1);
|
|
|
|
this->chunks[fnindex] =
|
|
std::pair<std::vector<uint32_t>,
|
|
std::vector<ByteCodeInstruction *>>(args,
|
|
fnInstructions);
|
|
instructions.push_back(
|
|
new ClosureInstruction((uint32_t)fnindex, false));
|
|
} else if (adv.nodeName == ClosureExpression && adv.nodes.size() == 2) {
|
|
//()=>{}
|
|
// Name => {}
|
|
//(a,b) => {}
|
|
// it has two args
|
|
std::vector<uint32_t> args;
|
|
GetFunctionArgs(args, adv.nodes[0]);
|
|
|
|
std::vector<ByteCodeInstruction *> fnInstructions;
|
|
size_t fnindex = this->chunks.size();
|
|
this->chunks.resize(fnindex + 1);
|
|
|
|
auto body = adv.nodes[1];
|
|
|
|
if (std::holds_alternative<AdvancedSyntaxNode>(body)) {
|
|
auto res = std::get<AdvancedSyntaxNode>(body);
|
|
if (res.nodeName == ScopeNode) {
|
|
res.nodeName = NodeList;
|
|
}
|
|
body = res;
|
|
}
|
|
|
|
GenNode(fnInstructions, body, 0, -1, -1, -1, -1);
|
|
|
|
this->chunks[fnindex] =
|
|
std::pair<std::vector<uint32_t>,
|
|
std::vector<ByteCodeInstruction *>>(args,
|
|
fnInstructions);
|
|
instructions.push_back(new ClosureInstruction((uint32_t)fnindex));
|
|
} else if (adv.nodeName == FunctionStatement && adv.nodes.size() == 2 &&
|
|
std::holds_alternative<AdvancedSyntaxNode>(adv.nodes[0])) {
|
|
// func NAME(ARGS) {}
|
|
// we need to disect NAME(ARGS) and {}
|
|
// then disect NAME and (ARGS)
|
|
auto fcall = std::get<AdvancedSyntaxNode>(adv.nodes[0]);
|
|
if (fcall.nodeName == FunctionCallExpression &&
|
|
adv.nodes.size() >= 1 &&
|
|
std::holds_alternative<AdvancedSyntaxNode>(fcall.nodes[0])) {
|
|
SyntaxNode args =
|
|
AdvancedSyntaxNode::Create(ParenthesesExpression, true, {});
|
|
if (fcall.nodes.size() == 2) {
|
|
args = AdvancedSyntaxNode::Create(ParenthesesExpression,
|
|
true, {fcall.nodes[1]});
|
|
}
|
|
SyntaxNode closure = AdvancedSyntaxNode::Create(
|
|
ClosureExpression, true, {args, adv.nodes[1]});
|
|
|
|
SyntaxNode assign = AdvancedSyntaxNode::Create(
|
|
AssignExpression, false, {fcall.nodes[0], closure});
|
|
GenNode(instructions, assign, scope, contscope, brkscope, contI,
|
|
brkI);
|
|
|
|
instructions.push_back(new SimpleInstruction(POP));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
void CodeGen::GetFunctionArgs(std::vector<SyntaxNode> &args, SyntaxNode n) {
|
|
AdvancedSyntaxNode sn;
|
|
if (std::holds_alternative<AdvancedSyntaxNode>(n) &&
|
|
(sn = std::get<AdvancedSyntaxNode>(n)).nodeName == CommaExpression &&
|
|
sn.nodes.size() == 2) {
|
|
GetFunctionArgs(args, sn.nodes[0]);
|
|
GetFunctionArgs(args, sn.nodes[1]);
|
|
} else {
|
|
args.push_back(n);
|
|
}
|
|
}
|
|
void CodeGen::GetFunctionArgs(std::vector<uint32_t> &name, SyntaxNode n) {
|
|
if (std::holds_alternative<std::nullptr_t>(n))
|
|
return;
|
|
|
|
if (std::holds_alternative<AdvancedSyntaxNode>(n)) {
|
|
auto res = std::get<AdvancedSyntaxNode>(n);
|
|
if (res.nodeName == ParenthesesExpression) {
|
|
for (auto n : res.nodes)
|
|
GetFunctionArgs(name, n);
|
|
} else if (res.nodeName == CommaExpression && res.nodes.size() == 2) {
|
|
GetFunctionArgs(name, res.nodes[0]);
|
|
GetFunctionArgs(name, res.nodes[1]);
|
|
} else if (res.nodeName == GetVariableExpression &&
|
|
res.nodes.size() == 1) {
|
|
if (std::holds_alternative<std::string>(res.nodes[0])) {
|
|
name.push_back(GetString(std::get<std::string>(res.nodes[0])));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CodeGen::GetFunctionName(std::vector<uint32_t> &name, SyntaxNode n) {
|
|
if (std::holds_alternative<AdvancedSyntaxNode>(n)) {
|
|
auto res = std::get<AdvancedSyntaxNode>(n);
|
|
if (res.nodeName == GetFieldExpression && res.nodes.size() == 2) {
|
|
GetFunctionName(name, res.nodes[0]);
|
|
if (std::holds_alternative<std::string>(res.nodes[1])) {
|
|
name.push_back(GetString(std::get<std::string>(res.nodes[1])));
|
|
}
|
|
|
|
} else if (res.nodeName == GetVariableExpression &&
|
|
res.nodes.size() == 1) {
|
|
if (std::holds_alternative<std::string>(res.nodes[0])) {
|
|
name.push_back(GetString(std::get<std::string>(res.nodes[0])));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CodeGen::GenRoot(SyntaxNode n) {
|
|
this->id = 0;
|
|
std::vector<ByteCodeInstruction *> rootInstructions;
|
|
size_t index = this->chunks.size();
|
|
this->chunks.resize(index + 1);
|
|
|
|
if (std::holds_alternative<AdvancedSyntaxNode>(n)) {
|
|
auto res = std::get<AdvancedSyntaxNode>(n);
|
|
|
|
if (res.nodeName == NodeList) {
|
|
for (auto item : res.nodes) {
|
|
if (std::holds_alternative<AdvancedSyntaxNode>(item)) {
|
|
std::string documentation = "";
|
|
auto res2 = std::get<AdvancedSyntaxNode>(item);
|
|
|
|
if (res2.nodeName == DocumentationStatement) {
|
|
if (res2.nodes.size() == 2) {
|
|
if (std::holds_alternative<std::string>(
|
|
res2.nodes[0]) &&
|
|
std::holds_alternative<AdvancedSyntaxNode>(
|
|
res2.nodes[1])) {
|
|
documentation =
|
|
std::get<std::string>(res2.nodes[0]);
|
|
auto j =
|
|
std::get<AdvancedSyntaxNode>(res2.nodes[1]);
|
|
if (j.nodeName == FunctionStatement ||
|
|
j.nodeName == EnumerableStatement) {
|
|
res2 = j;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (res2.nodeName == EnumerableStatement) {
|
|
res2 = AdvancedSyntaxNode::Create(
|
|
FunctionStatement, false,
|
|
{res2.nodes[0],
|
|
AdvancedSyntaxNode::Create(
|
|
ReturnStatement, false,
|
|
{AdvancedSyntaxNode::Create(
|
|
FunctionCallExpression, true,
|
|
{AdvancedSyntaxNode::Create(
|
|
GetVariableExpression, true,
|
|
{"YieldEmumerable"}),
|
|
AdvancedSyntaxNode::Create(
|
|
ClosureExpression, true,
|
|
{AdvancedSyntaxNode::Create(
|
|
ParenthesesExpression, true, {}),
|
|
res2.nodes[1]})})})});
|
|
}
|
|
if (res2.nodeName == FunctionStatement) {
|
|
if (res2.nodes.size() == 2) {
|
|
auto fcall = res2.nodes[0];
|
|
if (std::holds_alternative<AdvancedSyntaxNode>(
|
|
fcall)) {
|
|
auto fcalli =
|
|
std::get<AdvancedSyntaxNode>(fcall);
|
|
if (fcalli.nodeName == FunctionCallExpression) {
|
|
if (fcalli.nodes.size() >= 1) {
|
|
std::vector<uint32_t> functionName;
|
|
std::vector<uint32_t> args;
|
|
GetFunctionName(functionName,
|
|
fcalli.nodes[0]);
|
|
functionName.insert(
|
|
functionName.begin(),
|
|
{GetString(documentation)});
|
|
if (fcalli.nodes.size() == 2)
|
|
GetFunctionArgs(args,
|
|
fcalli.nodes[1]);
|
|
|
|
std::vector<ByteCodeInstruction *>
|
|
fnInstructions;
|
|
size_t fnindex = this->chunks.size();
|
|
this->chunks.resize(fnindex + 1);
|
|
|
|
GenNode(fnInstructions, res2.nodes[1],
|
|
0, -1, -1, -1, -1);
|
|
|
|
this->funcs.push_back(
|
|
std::pair<std::vector<uint32_t>,
|
|
uint32_t>(
|
|
functionName,
|
|
(uint32_t)fnindex));
|
|
|
|
this->chunks[fnindex] = std::pair<
|
|
std::vector<uint32_t>,
|
|
std::vector<ByteCodeInstruction *>>(
|
|
args, fnInstructions);
|
|
} else {
|
|
GenNode(rootInstructions, item, 0, -1,
|
|
-1, -1, -1);
|
|
GenPop(rootInstructions, item);
|
|
}
|
|
} else {
|
|
GenNode(rootInstructions, item, 0, -1, -1,
|
|
-1, -1);
|
|
GenPop(rootInstructions, item);
|
|
}
|
|
}
|
|
} else {
|
|
GenNode(rootInstructions, item, 0, -1, -1, -1, -1);
|
|
GenPop(rootInstructions, item);
|
|
}
|
|
} else {
|
|
GenNode(rootInstructions, item, 0, -1, -1, -1, -1);
|
|
GenPop(rootInstructions, item);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
GenNode(rootInstructions, n, 0, -1, -1, -1, -1);
|
|
GenPop(rootInstructions, n);
|
|
}
|
|
|
|
} else {
|
|
GenNode(rootInstructions, n, 0, -1, -1, -1, -1);
|
|
GenPop(rootInstructions, n);
|
|
}
|
|
|
|
this->chunks[index] =
|
|
std::pair<std::vector<uint32_t>, std::vector<ByteCodeInstruction *>>(
|
|
{}, rootInstructions);
|
|
}
|
|
|
|
uint32_t CodeGen::NewId() { return id++; }
|
|
|
|
void CodeGen::GenPop(std::vector<ByteCodeInstruction *> &instrs, SyntaxNode n) {
|
|
if (std::holds_alternative<AdvancedSyntaxNode>(n)) {
|
|
if (std::get<AdvancedSyntaxNode>(n).isExpression)
|
|
instrs.push_back(new SimpleInstruction(POP));
|
|
} else {
|
|
instrs.push_back(new SimpleInstruction(POP));
|
|
}
|
|
}
|
|
|
|
ResourceBase::~ResourceBase() {}
|
|
|
|
bool ResourceBase::IsEqual(ResourceBase *base) { return this == base; }
|
|
|
|
ResourceFile::ResourceFile() {}
|
|
ResourceFile::ResourceFile(std::string f) { this->file = f; }
|
|
ResourceFile::~ResourceFile() {}
|
|
|
|
uint32_t ResourceFile::GetLength(
|
|
std::shared_ptr<Tesses::Framework::Filesystem::VFS> embedFS) {
|
|
if (embedFS == nullptr)
|
|
return 0;
|
|
if (strm != nullptr)
|
|
return strm->GetLength();
|
|
this->strm = embedFS->OpenFile(this->file, "rb");
|
|
if (strm != nullptr)
|
|
return this->strm->GetLength();
|
|
|
|
return 0;
|
|
}
|
|
bool ResourceFile::IsEqual(ResourceBase *base) {
|
|
auto res = dynamic_cast<ResourceFile *>(base);
|
|
if (res != nullptr)
|
|
return this->file == res->file;
|
|
return ResourceBase::IsEqual(base);
|
|
}
|
|
void ResourceFile::Write(
|
|
std::shared_ptr<Tesses::Framework::Streams::Stream> output) {
|
|
if (this->strm != nullptr)
|
|
this->strm->CopyTo(output);
|
|
}
|
|
|
|
uint32_t ResourceByteArray::GetLength(
|
|
std::shared_ptr<Tesses::Framework::Filesystem::VFS> embedFS) {
|
|
return (uint32_t)this->data.size();
|
|
}
|
|
void ResourceByteArray::Write(
|
|
std::shared_ptr<Tesses::Framework::Streams::Stream> output) {
|
|
output->WriteBlock(this->data.data(), this->data.size());
|
|
}
|
|
|
|
} // namespace Tesses::CrossLang
|