#include "CrossLang.hpp" #include #include #include #include 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 items; for(auto instr : chunk.second) { auto lbl = dynamic_cast(instr); if(lbl != nullptr) { items[lbl->label] = offset; } offset += instr->Size(); } clength += (uint32_t)offset; for(auto instr : chunk.second) { auto jmp = dynamic_cast(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 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& instr) { instr.push_back(instruction); } ScopeEndTimesInstruction::ScopeEndTimesInstruction(uint32_t s) { this->n = s; } size_t ScopeEndTimesInstruction::Size() { return 5; } void ScopeEndTimesInstruction::Write(std::vector& instr) { instr.push_back(SCOPEENDTIMES); std::array 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& 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& instr) { instr.push_back((uint8_t)type); std::array 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& instr) { std::array 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& instr) { instr.push_back(PUSHSTRING); std::array 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& instr) { instr.push_back(PUSHRESOURCE); std::array 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& instr) { instr.push_back(this->hasScope ? PUSHCLOSURE : PUSHSCOPELESSCLOSURE); std::array 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& instr) { instr.push_back(PUSHDOUBLE); std::array 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& 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& instr) { instr.push_back(PUSHLONG); std::array 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& instructions, SyntaxNode n,int32_t scope,int32_t contscope, int32_t brkscope, int32_t contI, int32_t brkI) { if(std::holds_alternative(n)) { instructions.push_back(new SimpleInstruction(PUSHNULL)); } else if(std::holds_alternative(n)) { instructions.push_back(new SimpleInstruction(PUSHUNDEFINED)); } else if(std::holds_alternative(n)) { instructions.push_back(new SimpleInstruction(std::get(n) ? PUSHTRUE : PUSHFALSE)); } else if(std::holds_alternative(n)) { instructions.push_back(new StringInstruction(GetString(std::get(n)))); } else if(std::holds_alternative(n)) { instructions.push_back(new CharInstruction(std::get(n))); } else if(std::holds_alternative(n)) { instructions.push_back(new LongInstruction(std::get(n))); } else if(std::holds_alternative(n)) { instructions.push_back(new DoubleInstruction(std::get(n))); } else if(std::holds_alternative(n)) { auto adv = std::get(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 nodes_before; SyntaxNode currentCase = nullptr; std::vector currentNodes; std::string defaultJmp = {}; std::vector,std::vector>> snodes; if(std::holds_alternative(adv.nodes[1])) { auto body = std::get(adv.nodes[1]); if(body.nodeName == ScopeNode) { for(auto item : body.nodes) { if(std::holds_alternative(item)) { auto no = std::get(item); if(no.nodeName == CaseStatement || no.nodeName == DefaultStatement) { if(std::holds_alternative(currentCase)) { uint32_t jmpId = NewId(); std::string jmpIdStr = "__compGenJmp"; jmpIdStr.append(std::to_string(jmpId)); snodes.push_back(std::pair,std::vector>(std::pair(jmpIdStr,std::get(currentCase)),currentNodes)); currentNodes={}; } currentCase = no; continue; } } if(std::holds_alternative(currentCase)) { currentNodes.push_back(item); } else { nodes_before.push_back(item); } } if(std::holds_alternative(currentCase)) { uint32_t jmpId = NewId(); std::string jmpIdStr = "__compGenJmp"; jmpIdStr.append(std::to_string(jmpId)); snodes.push_back(std::pair,std::vector>(std::pair(jmpIdStr,std::get(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(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(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(adv.nodes[0])) { auto data = std::get(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 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 itms; if(adv.nodes.size() > 0) GetFunctionArgs(itms,adv.nodes[0]); for(auto item : itms) { if(std::holds_alternative(item)) { auto tkn = std::get(item); if(tkn.nodeName == GetVariableExpression && !tkn.nodes.empty() && std::holds_alternative(tkn.nodes[0])) { instructions.push_back(new StringInstruction(GetString(std::get(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(tkn.nodes[0])) { auto myTn = std::get(tkn.nodes[0]); if(myTn.nodeName == GetVariableExpression && !myTn.nodes.empty() && std::holds_alternative(myTn.nodes[0])) { instructions.push_back(new StringInstruction(GetString(std::get(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(adv.nodes[0])) { auto v = std::get(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 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 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(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(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(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(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(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(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(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(adv.nodes[0])) { instructions.push_back(new StringInstruction(GetString(std::get(adv.nodes[0])))); instructions.push_back(new SimpleInstruction(GETVARIABLE)); } else if(adv.nodeName == GetFieldExpression && adv.nodes.size() == 2 && std::holds_alternative(adv.nodes[1])) { GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI); instructions.push_back(new StringInstruction(GetString(std::get(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(adv.nodes[0])) { auto varNode = std::get(adv.nodes[0]); if(varNode.nodeName == GetVariableExpression && varNode.nodes.size() == 1 && std::holds_alternative(varNode.nodes[0])) { instructions.push_back(new StringInstruction(GetString(std::get(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(varNode.nodes[0])) { instructions.push_back(new StringInstruction(GetString(std::get(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(varNode.nodes[1])) { GenNode(instructions,varNode.nodes[0],scope,contscope,brkscope,contI,brkI); instructions.push_back(new StringInstruction(GetString(std::get(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(adv.nodes[0])) { std::string filename = std::get(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(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(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(adv.nodes[3])) { GenNode(instructions,AdvancedSyntaxNode::Create(DeferStatement,false, {adv.nodes[3]}),scope,contscope,brkscope,contI,brkI); } if(std::holds_alternative(adv.nodes[0]) && std::holds_alternative(adv.nodes[1]) && std::holds_alternative(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 args; GetFunctionArgs(args, adv.nodes[0]); std::vector fnInstructions; size_t fnindex=this->chunks.size(); this->chunks.resize(fnindex+1); auto body = adv.nodes[1]; if(std::holds_alternative(body)) { auto res = std::get(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>(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 args; GetFunctionArgs(args, adv.nodes[0]); std::vector fnInstructions; size_t fnindex=this->chunks.size(); this->chunks.resize(fnindex+1); auto body = adv.nodes[1]; if(std::holds_alternative(body)) { auto res = std::get(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>(args, fnInstructions); instructions.push_back(new ClosureInstruction((uint32_t)fnindex)); } else if(adv.nodeName == EnumerableStatement && adv.nodes.size() == 2 && std::holds_alternative(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(adv.nodes[0])) { //func NAME(ARGS) {} //we need to disect NAME(ARGS) and {} //then disect NAME and (ARGS) auto fcall = std::get(adv.nodes[0]); if(fcall.nodeName == FunctionCallExpression && adv.nodes.size() >= 1 && std::holds_alternative(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& args, SyntaxNode n) { AdvancedSyntaxNode sn; if(std::holds_alternative(n) && (sn=std::get(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& name, SyntaxNode n) { if(std::holds_alternative(n)) return; if(std::holds_alternative(n)) { auto res = std::get(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(res.nodes[0])) { name.push_back(GetString(std::get(res.nodes[0]))); } } } } void CodeGen::GetFunctionName(std::vector& name,SyntaxNode n) { if(std::holds_alternative(n)) { auto res = std::get(n); if(res.nodeName == GetFieldExpression && res.nodes.size() == 2) { GetFunctionName(name, res.nodes[0]); if(std::holds_alternative(res.nodes[1])) { name.push_back(GetString(std::get(res.nodes[1]))); } } else if(res.nodeName == GetVariableExpression && res.nodes.size() == 1) { if(std::holds_alternative(res.nodes[0])) { name.push_back(GetString(std::get(res.nodes[0]))); } } } } void CodeGen::GenRoot(SyntaxNode n) { this->id = 0; std::vector rootInstructions; size_t index=this->chunks.size(); this->chunks.resize(index+1); if(std::holds_alternative(n)) { auto res = std::get(n); if(res.nodeName == NodeList) { for(auto item : res.nodes) { if(std::holds_alternative(item)) { std::string documentation = ""; auto res2 = std::get(item); if(res2.nodeName == DocumentationStatement) { if(res2.nodes.size() == 2) { if(std::holds_alternative(res2.nodes[0]) && std::holds_alternative(res2.nodes[1])) { documentation = std::get(res2.nodes[0]); auto j = std::get(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(fcall)) { auto fcalli = std::get(fcall); if(fcalli.nodeName == FunctionCallExpression) { if(fcalli.nodes.size() >= 1) { std::vector functionName; std::vector args; GetFunctionName(functionName,fcalli.nodes[0]); functionName.insert(functionName.begin(),{GetString(documentation)}); if(fcalli.nodes.size()==2) GetFunctionArgs(args, fcalli.nodes[1]); std::vector 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,uint32_t>(functionName,(uint32_t)fnindex)); this->chunks[fnindex] = std::pair,std::vector>(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>({},rootInstructions); } uint32_t CodeGen::NewId() { return id++; } void CodeGen::GenPop(std::vector& instrs,SyntaxNode n) { if(std::holds_alternative(n)) { if(std::get(n).isExpression) instrs.push_back(new SimpleInstruction(POP)); } else { instrs.push_back(new SimpleInstruction(POP)); } } }