Website Summary Files Commits Branches @commit @diff @stats
path: root / JSImpl / src / ByteCodeGenerator.cpp
diff options
context:
space:
mode:
Commit6ba49b30cf1e33fb0dd6782a404ec34b7964cb59 (patch)
Author
 Martin Dobrev <martindobrev0@gmail.com>
2020-11-24 18:06:26 +0200
Committer
 GitHub <noreply@github.com>
2020-11-24 18:06:26 +0200
Filesa89b314c4d0b942d2350b9adbd741d6fa3375bfb /JSImpl/src/ByteCodeGenerator.cpp
IPL-6ba49b30cf1e33fb0dd6782a404ec34b7964cb59.tar
IPL-6ba49b30cf1e33fb0dd6782a404ec34b7964cb59.tar.gz
IPL-6ba49b30cf1e33fb0dd6782a404ec34b7964cb59.zip
Parent4e883334a14ff22f12765204d6bf223d07c0298f (diff)
Feature/object getters (#101)
* Add member access expression. * Implement property getters. * Add test for property getters. * Add test for property setter. * Implement while and do-while Signed-off-by: Martin Dobrev <martindobrev0@gmail.com> * Add implement byte code generation for break/continue in for/while.
1 files changed, 119 insertions, 0 deletions
-rw-r--r--JSImpl/src/ByteCodeGenerator.cpp119
diff --git a/JSImpl/src/ByteCodeGenerator.cpp b/JSImpl/src/ByteCodeGenerator.cpp
index 31a80bd..4d5cb09 100644
--- a/JSImpl/src/ByteCodeGenerator.cpp
+++ b/JSImpl/src/ByteCodeGenerator.cpp
@@ -22,10 +22,15 @@ public:
virtual void Visit(EmptyExpression* e) override { (void)e; }
virtual void Visit(IfStatement* e) override;
virtual void Visit(ForStatement* e) override;
+ virtual void Visit(WhileStatement* e) override;
+ virtual void Visit(Break* e) override;
+ virtual void Visit(Continue* e) override;
virtual void Visit(UnaryExpression* e) override;
virtual void Visit(LiteralField* e) override;
virtual void Visit(LiteralObject* e) override;
virtual void Visit(LiteralString* e) override;
+ virtual void Visit(MemberAccess* e) override;
+ virtual void Visit(Call* e) override;
IPLString GetCode();
unsigned ResolveRegisterName(IPLString& name);
@@ -101,16 +106,62 @@ private:
void PushConst(double c);
IPLString CreateRegister();
bool CheckOpCode(int opcode) { return opcode >= Instruction::Type::FIRST && opcode <= Instruction::Type::LAST; }
+
+ void OpenBreakScope() { m_BreakScopeStack.push(IPLVector<size_t>()); };
+ void OpenContinueScope() { m_ContinueScopeStack.push(IPLVector<size_t>()); };
+ void CloseBreakScope(size_t addr);
+ void CloseContinueScope(size_t addr);
+ void PushBreak();
+ void PushContinue();
private:
IPLVector<IPLString> m_RegisterTable;
IPLVector<Instruction> m_Code;
IPLVector<IPLString> m_Source;
+ IPLStack<IPLVector<size_t>> m_BreakScopeStack;
+ IPLStack<IPLVector<size_t>> m_ContinueScopeStack;
+
IPLStack<IPLString> m_RegisterStack;
IPLString m_OutputCode;
ByteCodeGeneratorOptions m_Options;
};
+void ByteCodeGenerator::PushBreak()
+{
+ assert(!m_BreakScopeStack.empty());
+ auto addr = PushInstruction(Instruction::Type::JMP, 0);
+ m_BreakScopeStack.top().push_back(addr);
+}
+
+void ByteCodeGenerator::PushContinue()
+{
+ assert(!m_ContinueScopeStack.empty());
+ auto addr = PushInstruction(Instruction::Type::JMP, 0);
+ m_ContinueScopeStack.top().push_back(addr);
+}
+
+void ByteCodeGenerator::CloseBreakScope(size_t addr)
+{
+ auto currentScope = m_BreakScopeStack.top();
+ for (const auto& br : currentScope)
+ {
+ assert(m_Code[br].Descriptor == Instruction::Type::JMP);
+ m_Code[br].Values.Address[0] = addr;
+ }
+ m_BreakScopeStack.pop();
+};
+
+void ByteCodeGenerator::CloseContinueScope(size_t addr)
+{
+ auto currentScope = m_ContinueScopeStack.top();
+ for (const auto& br : currentScope)
+ {
+ assert(m_Code[br].Descriptor == Instruction::Type::JMP);
+ m_Code[br].Values.Address[0] = addr;
+ }
+ m_ContinueScopeStack.pop();
+};
+
size_t ByteCodeGenerator::PushInstruction(Instruction::Type opcode, const IPLString& arg0, const IPLString& arg1, const IPLString& arg2)
{
assert(CheckOpCode(opcode));
@@ -337,15 +388,60 @@ void ByteCodeGenerator::Visit(IfStatement* e)
void ByteCodeGenerator::Visit(ForStatement* e)
{
+ OpenBreakScope();
+ OpenContinueScope();
+
e->GetInitialization()->Accept(*this);
auto compareAddress = m_Code.size();
e->GetCondition()->Accept(*this);
auto endAddress = PushInstruction(Instruction::Type::JMPF, m_RegisterStack.top(), (size_t)0);
m_RegisterStack.pop();
e->GetBody()->Accept(*this);
+
+ auto iterationAddress = m_Code.size();
e->GetIteration()->Accept(*this);
+
PushInstruction(Instruction::Type::JMP, compareAddress);
m_Code[endAddress].Values.Address[0] = m_Code.size();
+
+ CloseBreakScope(m_Code.size());
+ CloseContinueScope(iterationAddress);
+}
+
+void ByteCodeGenerator::Visit(WhileStatement* e)
+{
+ auto startAddress = m_Code.size();
+
+ OpenBreakScope();
+ OpenContinueScope();
+
+ if (e->GetDoWhile())
+ {
+ e->GetBody()->Accept(*this);
+ e->GetCondition()->Accept(*this);
+ PushInstruction(Instruction::Type::JMPT, m_RegisterStack.top(), startAddress);
+ }
+ else {
+ e->GetCondition()->Accept(*this);
+ auto endAddress = PushInstruction(Instruction::Type::JMPF, m_RegisterStack.top(), (size_t)0);
+ m_RegisterStack.pop();
+ e->GetBody()->Accept(*this);
+ PushInstruction(Instruction::Type::JMP, startAddress);
+ m_Code[endAddress].Values.Address[0] = m_Code.size();
+ }
+
+ CloseBreakScope(m_Code.size());
+ CloseContinueScope(startAddress);
+}
+
+void ByteCodeGenerator::Visit(Break*)
+{
+ PushBreak();
+}
+
+void ByteCodeGenerator::Visit(Continue*)
+{
+ PushContinue();
}
void ByteCodeGenerator::Visit(IdentifierExpression* e)
@@ -485,6 +581,29 @@ void ByteCodeGenerator::Visit(LiteralString* e)
m_RegisterStack.push(stringReg);
}
+void ByteCodeGenerator::Visit(Call* e)
+{
+ e->GetObjectOrCall()->Accept(*this);
+ if (e->GetMember())
+ {
+ e->GetMember()->Accept(*this);
+ }
+}
+
+void ByteCodeGenerator::Visit(MemberAccess* e)
+{
+ auto objectReg = m_RegisterStack.top();
+ m_RegisterStack.pop();
+
+ auto identifierNameReg = CreateRegister();
+ PushInstruction(Instruction::Type::STRING, identifierNameReg, e->GetName());
+
+ auto resultReg = CreateRegister();
+ PushInstruction(Instruction::Type::GET, objectReg, identifierNameReg, resultReg);
+
+ m_RegisterStack.push(resultReg);
+}
+
unsigned ByteCodeGenerator::ResolveRegisterName(IPLString& name)
{
auto it = std::find_if(m_RegisterTable.begin(), m_RegisterTable.end(), [&](IPLString& current) {