1454 lines
61 KiB
C++
1454 lines
61 KiB
C++
#include "CrossLang.hpp"
|
|
#include <iostream>
|
|
#include <array>
|
|
#include <map>
|
|
#include <cstring>
|
|
namespace Tesses::CrossLang
|
|
{
|
|
void Write(Tesses::Framework::Streams::Stream* strm, uint8_t* buffer, size_t len)
|
|
{
|
|
strm->WriteBlock(buffer,len);
|
|
}
|
|
void WriteInt(Tesses::Framework::Streams::Stream* strm,uint32_t v)
|
|
{
|
|
uint8_t buffer[4];
|
|
BitConverter::FromUint32BE(buffer[0],v);
|
|
Write(strm,buffer,4);
|
|
}
|
|
void WriteString(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;
|
|
}
|
|
}
|
|
|
|
void CodeGen::Save(Tesses::Framework::Filesystem::VFS* vfs, Tesses::Framework::Streams::Stream* stream)
|
|
{
|
|
TVMVersion runtime_version(TVM_MAJOR,TVM_MINOR,TVM_PATCH,TVM_BUILD,TVM_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++;
|
|
}
|
|
if(!this->icon.empty())
|
|
{
|
|
this->GetResource(this->icon);
|
|
|
|
}
|
|
for(auto& res : this->res)
|
|
sections++;
|
|
|
|
if(!this->icon.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());
|
|
}
|
|
|
|
for(auto& reso : res)
|
|
{
|
|
memcpy(buffer,"RESO",4);
|
|
Write(stream,buffer,4);
|
|
|
|
if(vfs == nullptr)
|
|
{
|
|
WriteInt(stream,0);
|
|
continue;
|
|
}
|
|
auto f = vfs->OpenFile(reso,"rb");
|
|
if(f != NULL)
|
|
{
|
|
|
|
uint32_t len = (uint32_t)f->GetLength();
|
|
|
|
WriteInt(stream,len);
|
|
uint8_t buff[1024];
|
|
size_t read;
|
|
do {
|
|
read = f->Read(buff,1024);
|
|
Write(stream,buff,read);
|
|
} while(read > 0);
|
|
delete f;
|
|
}
|
|
else
|
|
{
|
|
WriteInt(stream,0);
|
|
}
|
|
}
|
|
if(!this->icon.empty())
|
|
{
|
|
memcpy(buffer,"ICON",4);
|
|
Write(stream,buffer,4);
|
|
WriteInt(stream,4);
|
|
WriteInt(stream,this->GetResource(this->icon));
|
|
|
|
}
|
|
}
|
|
|
|
|
|
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());
|
|
}
|
|
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::string res)
|
|
{
|
|
for(uint32_t i = 0; i < (uint32_t)this->res.size();i++)
|
|
{
|
|
if(this->res[i] == res) return i;
|
|
}
|
|
uint32_t resI = (uint32_t)this->res.size();
|
|
this->res.push_back(res);
|
|
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));}
|
|
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<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 == 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() && std::holds_alternative<std::string>(tkn.nodes[0]))
|
|
{
|
|
instructions.push_back(new StringInstruction(GetString(std::get<std::string>(tkn.nodes[0]))));
|
|
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() && std::holds_alternative<std::string>(myTn.nodes[0]))
|
|
{
|
|
instructions.push_back(new StringInstruction(GetString(std::get<std::string>(myTn.nodes[0]))));
|
|
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 == 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
|
|
{
|
|
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
|
|
{
|
|
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 && std::holds_alternative<std::string>(adv.nodes[0]))
|
|
{
|
|
instructions.push_back(new StringInstruction(GetString(std::get<std::string>(adv.nodes[0]))));
|
|
instructions.push_back(new SimpleInstruction(GETVARIABLE));
|
|
}
|
|
else if(adv.nodeName == GetFieldExpression && adv.nodes.size() == 2 && std::holds_alternative<std::string>(adv.nodes[1]))
|
|
{
|
|
|
|
GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI);
|
|
instructions.push_back(new StringInstruction(GetString(std::get<std::string>(adv.nodes[1]))));
|
|
|
|
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 && std::holds_alternative<std::string>(varNode.nodes[0]))
|
|
{
|
|
instructions.push_back(new StringInstruction(GetString(std::get<std::string>(varNode.nodes[0]))));
|
|
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]))
|
|
{
|
|
instructions.push_back(new StringInstruction(GetString(std::get<std::string>(varNode.nodes[0]))));
|
|
GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI);
|
|
instructions.push_back(new SimpleInstruction(DECLAREVARIABLE));
|
|
}
|
|
else if(varNode.nodeName == GetFieldExpression && varNode.nodes.size() == 2 && std::holds_alternative<std::string>(varNode.nodes[1]))
|
|
{
|
|
GenNode(instructions,varNode.nodes[0],scope,contscope,brkscope,contI,brkI);
|
|
instructions.push_back(new StringInstruction(GetString(std::get<std::string>(varNode.nodes[1]))));
|
|
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 == ThrowStatement && adv.nodes.size() == 1)
|
|
{
|
|
GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI);
|
|
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(filename)));
|
|
|
|
}
|
|
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,brkscope,contI,brkI);
|
|
GenNode(instructions,AdvancedSyntaxNode::Create(ScopelessClosureExpression,true,{
|
|
AdvancedSyntaxNode::Create(ParenthesesExpression,true,{adv.nodes[2]}),
|
|
adv.nodes[1]
|
|
}),scope,contscope,brkscope,contI,brkI);
|
|
instructions.push_back(new SimpleInstruction(TRYCATCH));
|
|
uint32_t compGenId = NewId();
|
|
std::string compGenIttr = "__compGenRetThing";
|
|
compGenIttr.append(std::to_string(compGenId));
|
|
instructions.push_back(new JumpStyleInstruction(JMPUNDEFINED, compGenIttr));
|
|
instructions.push_back(new SimpleInstruction(RET));
|
|
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,-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,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 == EnumerableStatement && adv.nodes.size() == 2 && std::holds_alternative<AdvancedSyntaxNode>(adv.nodes[0]))
|
|
{
|
|
SyntaxNode n = AdvancedSyntaxNode::Create(FunctionStatement,false,{
|
|
adv.nodes[0],
|
|
AdvancedSyntaxNode::Create(ReturnStatement,false,{
|
|
AdvancedSyntaxNode::Create(FunctionCallExpression,true,{
|
|
AdvancedSyntaxNode::Create(GetVariableExpression,true,{"YieldEmumerable"}),
|
|
AdvancedSyntaxNode::Create(ClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), adv.nodes[1]})
|
|
})
|
|
})
|
|
});
|
|
GenNode(instructions,n,scope,contscope,brkscope,contI,brkI);
|
|
|
|
}
|
|
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));
|
|
}
|
|
}
|
|
} |