From 60ff8830ed0d62820205420da2678cb3b410a66e Mon Sep 17 00:00:00 2001 From: martin dobrev Date: Wed, 14 Nov 2018 08:50:00 +0200 Subject: Byte code generator initial commit. --- JSImpl/src/ByteCodeGenerator.cpp | 390 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 390 insertions(+) create mode 100644 JSImpl/src/ByteCodeGenerator.cpp (limited to 'JSImpl/src/ByteCodeGenerator.cpp') diff --git a/JSImpl/src/ByteCodeGenerator.cpp b/JSImpl/src/ByteCodeGenerator.cpp new file mode 100644 index 0000000..349c93a --- /dev/null +++ b/JSImpl/src/ByteCodeGenerator.cpp @@ -0,0 +1,390 @@ +#include "ByteCodeGenerator.h" +#include "ExpressionVisitor.h" +#include + +class ByteCodeGenerator : public ExpressionVisitor +{ +public: + ByteCodeGenerator() {}; + ~ByteCodeGenerator() {}; + + + virtual void Visit(FunctionDeclaration* e) override; + virtual void Visit(BlockStatement* e) override; + virtual void Visit(BinaryExpression* e) override; + virtual void Visit(LiteralNumber* e) override; + virtual void Visit(TopStatements* e) override; + virtual void Visit(ListExpression* e) override; + virtual void Visit(VariableDefinitionExpression* e) override; + + IPLString GetCode(); + unsigned ResolveRegisterName(IPLString& name); +private: + + struct Instruction + { + enum Type : char + { + ADD, + SUB, + MUL, + DIV, + MOD, + MOV, + PRINT, + READ, + CALL, + RET, + JMP, + JMPT, + JMPF, + DUP, + PUSH, + POP, + SAVE, + RESTORE, + LESS, + EQ, + LEQ, + GETG, + SETG, + GETUP, + SETUP, + GET, + SET, + INC, + DEC, + AND, + OR, + XOR, + NOT, + THROW, + CATCH, + CONST, + STRING, + HALT, + }; + + Type Descriptor; + IPLString Args[3]; + double Number; + }; + IPLVector m_RegisterTable; + IPLVector m_Code; + + IPLStack m_RegisterStack; + unsigned m_CurrentStackPointer; IPLString m_OutputCode; }; + +void ByteCodeGenerator::Visit(FunctionDeclaration* e) +{ + e->GetBody()->Accept(*this); +} + +void ByteCodeGenerator::Visit(ListExpression* e) +{ + auto& statements = e->GetValues(); + for (auto& s : statements) + { + s->Accept(*this); + } +} + +void ByteCodeGenerator::Visit(BlockStatement* e) +{ + auto& statements = e->GetValues(); + for (auto& s : statements) + { + s->Accept(*this); + } +} + +void ByteCodeGenerator::Visit(TopStatements* e) +{ + auto& statements = e->GetValues(); + for (auto& s : statements) + { + Instruction current; + current.Descriptor = Instruction::Type::PUSH; + auto index = m_Code.size(); + m_Code.push_back(current); + s->Accept(*this); + m_Code[index].Number = (unsigned)m_RegisterTable.size(); + + current.Descriptor = Instruction::Type::POP; + current.Number = (unsigned)m_RegisterTable.size(); + m_Code.push_back(current); + } +} + +void ByteCodeGenerator::Visit(VariableDefinitionExpression* e) +{ + m_RegisterTable.push_back(e->GetName()); + if (e->GetValue()) + { + e->GetValue()->Accept(*this); + } + Instruction current; + current.Descriptor = Instruction::Type::MOV; + current.Args[0] = e->GetName(); + current.Args[1] = m_RegisterStack.top(); + m_RegisterStack.pop(); + m_Code.push_back(current); +} + +void ByteCodeGenerator::Visit(BinaryExpression* e) +{ + Instruction current; + IPLString regName = IPLString ("tmp"); + regName += std::to_string(m_RegisterTable.size()); + m_RegisterTable.push_back(regName); + m_RegisterStack.push(regName); + current.Args[0] = regName; + + e->GetLeft()->Accept(*this); + current.Args[1] = m_RegisterStack.top(); + m_RegisterStack.pop(); + + e->GetRight()->Accept(*this); + current.Args[2] = m_RegisterStack.top(); + m_RegisterStack.pop(); + + switch (e->GetOperator()) { + case TokenType::Plus: + current.Descriptor = Instruction::Type::ADD; + break; + case TokenType::Minus: + current.Descriptor = Instruction::Type::SUB; + break; + case TokenType::Star: + current.Descriptor = Instruction::Type::MUL; + break; + case TokenType::Division: + current.Descriptor = Instruction::Type::DIV; + break; + case TokenType::Less: + current.Descriptor = Instruction::Type::LESS; + break; + case TokenType::EqualEqual: + current.Descriptor = Instruction::Type::EQ; + break; + case TokenType::BangEqual: + NOT_IMPLEMENTED; + break; + case TokenType::Equal: + current.Descriptor = Instruction::Type::MOV; + current.Args[0] = current.Args[1]; + current.Args[1] = current.Args[2]; + break; + default: + NOT_IMPLEMENTED; + } + m_Code.push_back(current); +} + +void ByteCodeGenerator::Visit(LiteralNumber* e) +{ + Instruction current; + + IPLString regName = IPLString("const"); + regName += std::to_string(m_RegisterTable.size()); + m_RegisterTable.push_back(regName); + m_RegisterStack.push(regName); + + current.Descriptor = Instruction::Type::CONST; + current.Args[0] = regName; + current.Number = e->GetValue(); + + m_Code.push_back(current); +} + +unsigned ByteCodeGenerator::ResolveRegisterName(IPLString& name) +{ + auto it = std::find_if(m_RegisterTable.begin(), m_RegisterTable.end(), [&](IPLString& current) { + return name == current; + }); + return unsigned(it - m_RegisterTable.begin()); +} + +IPLString ByteCodeGenerator::GetCode() +{ + IPLString result; + + for (auto& i : m_Code) + { + switch (i.Descriptor) + { + case ByteCodeGenerator::Instruction::ADD: + result += "add r" + std::to_string(ResolveRegisterName(i.Args[0])) + + " r" + std::to_string(ResolveRegisterName(i.Args[1])) + + " r" + std::to_string(ResolveRegisterName(i.Args[2])) + '\n'; + + break; + case ByteCodeGenerator::Instruction::SUB: + result += "sub r" + std::to_string(ResolveRegisterName(i.Args[0])) + + " r" + std::to_string(ResolveRegisterName(i.Args[1])) + + " r" + std::to_string(ResolveRegisterName(i.Args[2])) + '\n'; + break; + case ByteCodeGenerator::Instruction::MUL: + result += "mul r" + std::to_string(ResolveRegisterName(i.Args[0])) + + " r" + std::to_string(ResolveRegisterName(i.Args[1])) + + " r" + std::to_string(ResolveRegisterName(i.Args[2])) + '\n'; + break; + case ByteCodeGenerator::Instruction::DIV: + result += "div r" + std::to_string(ResolveRegisterName(i.Args[0])) + + " r" + std::to_string(ResolveRegisterName(i.Args[1])) + + " r" + std::to_string(ResolveRegisterName(i.Args[2])) + '\n'; + break; + case ByteCodeGenerator::Instruction::MOD: + result += "mod r" + std::to_string(ResolveRegisterName(i.Args[0])) + + " r" + std::to_string(ResolveRegisterName(i.Args[1])) + + " r" + std::to_string(ResolveRegisterName(i.Args[2])) + '\n'; + break; + case ByteCodeGenerator::Instruction::MOV: + result += "mov r" + std::to_string(ResolveRegisterName(i.Args[0])) + + " r" + std::to_string(ResolveRegisterName(i.Args[1])) + '\n'; + break; + case ByteCodeGenerator::Instruction::PRINT: + result += "print r" + std::to_string(ResolveRegisterName(i.Args[0])) + '\n'; + break; + case ByteCodeGenerator::Instruction::READ: + result += "read"; + NOT_IMPLEMENTED; + break; + case ByteCodeGenerator::Instruction::CALL: + result += "call"; + NOT_IMPLEMENTED; + break; + case ByteCodeGenerator::Instruction::RET: + result += "ret"; + NOT_IMPLEMENTED; + break; + case ByteCodeGenerator::Instruction::JMP: + result += "jmp"; + NOT_IMPLEMENTED; + break; + case ByteCodeGenerator::Instruction::JMPT: + result += "jmpt r" + std::to_string(ResolveRegisterName(i.Args[0])) + '\n'; + break; + case ByteCodeGenerator::Instruction::JMPF: + result += "jmpf r" + std::to_string(ResolveRegisterName(i.Args[0])) + '\n'; + break; + case ByteCodeGenerator::Instruction::DUP: + result += "dup"; + NOT_IMPLEMENTED; + break; + case ByteCodeGenerator::Instruction::PUSH: + result += "push " + std::to_string((unsigned)i.Number) + '\n'; + break; + case ByteCodeGenerator::Instruction::POP: + result += "pop " + std::to_string((unsigned)i.Number) + '\n'; + break; + case ByteCodeGenerator::Instruction::SAVE: + result += "save"; + NOT_IMPLEMENTED; + break; + case ByteCodeGenerator::Instruction::RESTORE: + result += "restore"; + NOT_IMPLEMENTED; + break; + case ByteCodeGenerator::Instruction::LESS: + result += "less r" + std::to_string(ResolveRegisterName(i.Args[0])) + + " r" + std::to_string(ResolveRegisterName(i.Args[1])) + + " r" + std::to_string(ResolveRegisterName(i.Args[2])) + '\n'; + break; + case ByteCodeGenerator::Instruction::EQ: + result += "eq r" + std::to_string(ResolveRegisterName(i.Args[0])) + + " r" + std::to_string(ResolveRegisterName(i.Args[1])) + + " r" + std::to_string(ResolveRegisterName(i.Args[2])) + '\n'; + break; + case ByteCodeGenerator::Instruction::LEQ: + result += "leq r" + std::to_string(ResolveRegisterName(i.Args[0])) + + " r" + std::to_string(ResolveRegisterName(i.Args[1])) + + " r" + std::to_string(ResolveRegisterName(i.Args[2])) + '\n'; + break; + case ByteCodeGenerator::Instruction::GETG: + result += "getg"; + NOT_IMPLEMENTED; + break; + case ByteCodeGenerator::Instruction::SETG: + result += "setg"; + NOT_IMPLEMENTED; + break; + case ByteCodeGenerator::Instruction::GETUP: + result += "getup"; + NOT_IMPLEMENTED; + break; + case ByteCodeGenerator::Instruction::SETUP: + result += "setup"; + NOT_IMPLEMENTED; + break; + case ByteCodeGenerator::Instruction::GET: + result += "get"; + NOT_IMPLEMENTED; + break; + case ByteCodeGenerator::Instruction::SET: + result += "set"; + NOT_IMPLEMENTED; + break; + case ByteCodeGenerator::Instruction::INC: + result += "inc"; + NOT_IMPLEMENTED; + break; + case ByteCodeGenerator::Instruction::DEC: + result += "dec"; + NOT_IMPLEMENTED; + break; + case ByteCodeGenerator::Instruction::AND: + result += "and r" + std::to_string(ResolveRegisterName(i.Args[0])) + + " r" + std::to_string(ResolveRegisterName(i.Args[1])) + + " r" + std::to_string(ResolveRegisterName(i.Args[2])) + '\n'; + break; + case ByteCodeGenerator::Instruction::OR: + result += "or r" + std::to_string(ResolveRegisterName(i.Args[0])) + + " r" + std::to_string(ResolveRegisterName(i.Args[1])) + + " r" + std::to_string(ResolveRegisterName(i.Args[2])) + '\n'; + break; + case ByteCodeGenerator::Instruction::XOR: + result += "xor r" + std::to_string(ResolveRegisterName(i.Args[0])) + + " r" + std::to_string(ResolveRegisterName(i.Args[1])) + + " r" + std::to_string(ResolveRegisterName(i.Args[2])) + '\n'; + break; + case ByteCodeGenerator::Instruction::NOT: + result += "not"; + NOT_IMPLEMENTED; + break; + case ByteCodeGenerator::Instruction::THROW: + result += "throw"; + NOT_IMPLEMENTED; + break; + case ByteCodeGenerator::Instruction::CATCH: + result += "catch"; + NOT_IMPLEMENTED; + break; + case ByteCodeGenerator::Instruction::CONST: + result += "const r" + std::to_string(ResolveRegisterName(i.Args[0])) + " " + std::to_string(i.Number) + '\n'; + break; + case ByteCodeGenerator::Instruction::STRING: + result += "string"; + NOT_IMPLEMENTED; + break; + case ByteCodeGenerator::Instruction::HALT: + result += "halt\n"; + break; + default: + NOT_IMPLEMENTED; + break; + + } + } + + result += "halt\n"; + return result; +} + +IPLString GenerateByteCode(ExpressionPtr program) +{ + ByteCodeGenerator generator; + program->Accept(generator); + + return generator.GetCode(); +} \ No newline at end of file -- cgit v1.3.1-23-gd82d From 532a594a0efac2e7624e1c9ddce8fb6d81dace4f Mon Sep 17 00:00:00 2001 From: martin dobrev Date: Wed, 14 Nov 2018 09:33:50 +0200 Subject: Implement if --- JSImpl/src/ByteCodeGenerator.cpp | 117 +++++++++++++++++++++++++++++---------- JSImpl/src/main.cpp | 14 ++++- 2 files changed, 99 insertions(+), 32 deletions(-) (limited to 'JSImpl/src/ByteCodeGenerator.cpp') diff --git a/JSImpl/src/ByteCodeGenerator.cpp b/JSImpl/src/ByteCodeGenerator.cpp index 349c93a..385284d 100644 --- a/JSImpl/src/ByteCodeGenerator.cpp +++ b/JSImpl/src/ByteCodeGenerator.cpp @@ -16,6 +16,9 @@ public: virtual void Visit(TopStatements* e) override; virtual void Visit(ListExpression* e) override; virtual void Visit(VariableDefinitionExpression* e) override; + virtual void Visit(IdentifierExpression* e) override; + virtual void Visit(EmptyExpression* e) override { (void)e; } + virtual void Visit(IfStatement* e) override; IPLString GetCode(); unsigned ResolveRegisterName(IPLString& name); @@ -101,19 +104,20 @@ void ByteCodeGenerator::Visit(BlockStatement* e) void ByteCodeGenerator::Visit(TopStatements* e) { auto& statements = e->GetValues(); + + Instruction current; + current.Descriptor = Instruction::Type::PUSH; + auto index = m_Code.size(); + m_Code.push_back(current); for (auto& s : statements) { - Instruction current; - current.Descriptor = Instruction::Type::PUSH; - auto index = m_Code.size(); - m_Code.push_back(current); s->Accept(*this); - m_Code[index].Number = (unsigned)m_RegisterTable.size(); - - current.Descriptor = Instruction::Type::POP; - current.Number = (unsigned)m_RegisterTable.size(); - m_Code.push_back(current); } + m_Code[index].Number = (unsigned)m_RegisterTable.size(); + + current.Descriptor = Instruction::Type::POP; + current.Number = (unsigned)m_RegisterTable.size(); + m_Code.push_back(current); } void ByteCodeGenerator::Visit(VariableDefinitionExpression* e) @@ -123,22 +127,20 @@ void ByteCodeGenerator::Visit(VariableDefinitionExpression* e) { e->GetValue()->Accept(*this); } - Instruction current; - current.Descriptor = Instruction::Type::MOV; - current.Args[0] = e->GetName(); - current.Args[1] = m_RegisterStack.top(); - m_RegisterStack.pop(); - m_Code.push_back(current); + if (!m_RegisterStack.empty()) + { + Instruction current; + current.Descriptor = Instruction::Type::MOV; + current.Args[0] = e->GetName(); + current.Args[1] = m_RegisterStack.top(); + m_RegisterStack.pop(); + m_Code.push_back(current); + } } void ByteCodeGenerator::Visit(BinaryExpression* e) { Instruction current; - IPLString regName = IPLString ("tmp"); - regName += std::to_string(m_RegisterTable.size()); - m_RegisterTable.push_back(regName); - m_RegisterStack.push(regName); - current.Args[0] = regName; e->GetLeft()->Accept(*this); current.Args[1] = m_RegisterStack.top(); @@ -148,6 +150,22 @@ void ByteCodeGenerator::Visit(BinaryExpression* e) current.Args[2] = m_RegisterStack.top(); m_RegisterStack.pop(); + if (e->GetOperator() == TokenType::Equal) + { + current.Descriptor = Instruction::Type::MOV; + current.Args[0] = current.Args[1]; + current.Args[1] = current.Args[2]; + m_Code.push_back(current); + return; + } + + + IPLString regName = IPLString ("tmp"); + regName += std::to_string(m_RegisterTable.size()); + m_RegisterTable.push_back(regName); + m_RegisterStack.push(regName); + current.Args[0] = regName; + switch (e->GetOperator()) { case TokenType::Plus: current.Descriptor = Instruction::Type::ADD; @@ -171,9 +189,7 @@ void ByteCodeGenerator::Visit(BinaryExpression* e) NOT_IMPLEMENTED; break; case TokenType::Equal: - current.Descriptor = Instruction::Type::MOV; - current.Args[0] = current.Args[1]; - current.Args[1] = current.Args[2]; + break; default: NOT_IMPLEMENTED; @@ -181,6 +197,44 @@ void ByteCodeGenerator::Visit(BinaryExpression* e) m_Code.push_back(current); } +void ByteCodeGenerator::Visit(IfStatement* e) +{ + Instruction current; + e->GetCondition()->Accept(*this); + current.Descriptor = Instruction::Type::JMPF; + current.Args[0] = m_RegisterStack.top(); + current.Number = 0.0; + m_RegisterStack.pop(); + auto ifIndex = m_Code.size(); + m_Code.push_back(current); + + e->GetIfStatement()->Accept(*this); + + if (e->GetElseStatement()) + { + current.Descriptor = Instruction::Type::JMP; + m_Code.push_back(current); + auto afterTrueBlock = m_Code.size(); + + e->GetElseStatement()->Accept(*this); + + // Patching + m_Code[ifIndex].Number = (double)afterTrueBlock; + m_Code[afterTrueBlock - 1].Number = (double)m_Code.size(); + } + else + { + m_Code[ifIndex].Number = (double)m_Code.size(); + + } + +} + +void ByteCodeGenerator::Visit(IdentifierExpression* e) +{ + m_RegisterStack.push(e->GetName()); +} + void ByteCodeGenerator::Visit(LiteralNumber* e) { Instruction current; @@ -208,9 +262,10 @@ unsigned ByteCodeGenerator::ResolveRegisterName(IPLString& name) IPLString ByteCodeGenerator::GetCode() { IPLString result; - + auto programCounter = 0; for (auto& i : m_Code) { + result += std::to_string(programCounter) + ": "; switch (i.Descriptor) { case ByteCodeGenerator::Instruction::ADD: @@ -259,24 +314,25 @@ IPLString ByteCodeGenerator::GetCode() NOT_IMPLEMENTED; break; case ByteCodeGenerator::Instruction::JMP: - result += "jmp"; - NOT_IMPLEMENTED; + result += "jmp " + std::to_string((size_t)i.Number) + '\n'; break; case ByteCodeGenerator::Instruction::JMPT: - result += "jmpt r" + std::to_string(ResolveRegisterName(i.Args[0])) + '\n'; + result += "jmpt r" + std::to_string(ResolveRegisterName(i.Args[0])) + + " " + std::to_string((size_t)i.Number) + '\n'; break; case ByteCodeGenerator::Instruction::JMPF: - result += "jmpf r" + std::to_string(ResolveRegisterName(i.Args[0])) + '\n'; + result += "jmpf r" + std::to_string(ResolveRegisterName(i.Args[0])) + + " " + std::to_string((size_t)i.Number) + '\n'; break; case ByteCodeGenerator::Instruction::DUP: result += "dup"; NOT_IMPLEMENTED; break; case ByteCodeGenerator::Instruction::PUSH: - result += "push " + std::to_string((unsigned)i.Number) + '\n'; + result += "push " + std::to_string((size_t)i.Number) + '\n'; break; case ByteCodeGenerator::Instruction::POP: - result += "pop " + std::to_string((unsigned)i.Number) + '\n'; + result += "pop " + std::to_string((size_t)i.Number) + '\n'; break; case ByteCodeGenerator::Instruction::SAVE: result += "save"; @@ -375,6 +431,7 @@ IPLString ByteCodeGenerator::GetCode() break; } + ++programCounter; } result += "halt\n"; diff --git a/JSImpl/src/main.cpp b/JSImpl/src/main.cpp index a10e4d1..b2fb83d 100644 --- a/JSImpl/src/main.cpp +++ b/JSImpl/src/main.cpp @@ -2,6 +2,7 @@ #include "Parser.h" #include "ASTPrinter.h" #include "ASTInterpreter.h" +#include "ByteCodeGenerator.h" #include #include @@ -62,11 +63,20 @@ void InteractiveInterpreter() } while (true); } +void Generate() +{ + IPLVector tokens; + //Tokenize("var a = 0; var b = a + 123;a+b;", tokens); + Tokenize("var a; if(a < 4) { a = 8;} else { a = 2} ", tokens); + + std::cout << GenerateByteCode(Parse(tokens)); +} + int main() { //RunParseCalc(); - InteractiveInterpreter(); - + //InteractiveInterpreter(); + Generate(); #if defined(_WIN32) std::system("pause"); #endif -- cgit v1.3.1-23-gd82d From b2b2fe9c2c404681fb479018b52a07f3133b7d6b Mon Sep 17 00:00:00 2001 From: martin dobrev Date: Thu, 15 Nov 2018 09:39:00 +0200 Subject: Implement byte generation for "for statement" --- JSImpl/src/ByteCodeGenerator.cpp | 72 ++++++++++++++++++++++++++++++++++------ JSImpl/src/main.cpp | 4 +-- 2 files changed, 64 insertions(+), 12 deletions(-) (limited to 'JSImpl/src/ByteCodeGenerator.cpp') diff --git a/JSImpl/src/ByteCodeGenerator.cpp b/JSImpl/src/ByteCodeGenerator.cpp index 385284d..fefed78 100644 --- a/JSImpl/src/ByteCodeGenerator.cpp +++ b/JSImpl/src/ByteCodeGenerator.cpp @@ -19,11 +19,12 @@ public: virtual void Visit(IdentifierExpression* e) override; virtual void Visit(EmptyExpression* e) override { (void)e; } virtual void Visit(IfStatement* e) override; + virtual void Visit(ForStatement* e) override; IPLString GetCode(); unsigned ResolveRegisterName(IPLString& name); -private: +private: struct Instruction { enum Type : char @@ -72,12 +73,50 @@ private: IPLString Args[3]; double Number; }; + size_t PushInstruction(Instruction::Type opcode, IPLString& arg1, IPLString& arg2, IPLString& arg3); + size_t PushInstruction(Instruction::Type opcode, size_t Address); + size_t PushInstruction(Instruction::Type opcode, IPLString& arg1, size_t Address); + +private: IPLVector m_RegisterTable; IPLVector m_Code; IPLStack m_RegisterStack; unsigned m_CurrentStackPointer; IPLString m_OutputCode; }; +size_t ByteCodeGenerator::PushInstruction(Instruction::Type opcode, IPLString& arg0, IPLString& arg1, IPLString& arg2) +{ + Instruction ins; + ins.Descriptor = opcode; + ins.Args[0] = arg0; + ins.Args[1] = arg1; + ins.Args[2] = arg2; + auto address = m_Code.size(); + m_Code.push_back(ins); + return address; +} + +size_t ByteCodeGenerator::PushInstruction(Instruction::Type opcode, size_t Address) +{ + Instruction ins; + ins.Descriptor = opcode; + ins.Number = (double)Address; + auto address = m_Code.size(); + m_Code.push_back(ins); + return address; +} + +size_t ByteCodeGenerator::PushInstruction(Instruction::Type opcode, IPLString& arg0, size_t Address) +{ + Instruction ins; + ins.Descriptor = opcode; + ins.Args[0] = arg0; + ins.Number = (double)Address; + auto address = m_Code.size(); + m_Code.push_back(ins); + return address; +} + void ByteCodeGenerator::Visit(FunctionDeclaration* e) { e->GetBody()->Accept(*this); @@ -122,6 +161,14 @@ void ByteCodeGenerator::Visit(TopStatements* e) void ByteCodeGenerator::Visit(VariableDefinitionExpression* e) { + auto it = std::find_if(m_RegisterTable.begin(), m_RegisterTable.end(), [&](IPLString& current) { + return e->GetName() == current; + }); + if (it != m_RegisterTable.end()) + { + // TODO: error double definitions + return; + } m_RegisterTable.push_back(e->GetName()); if (e->GetValue()) { @@ -225,9 +272,20 @@ void ByteCodeGenerator::Visit(IfStatement* e) else { m_Code[ifIndex].Number = (double)m_Code.size(); - } +} +void ByteCodeGenerator::Visit(ForStatement* e) +{ + e->GetInitialization()->Accept(*this); + auto compareAddress = m_Code.size(); + e->GetCondition()->Accept(*this); + auto endAddress = PushInstruction(Instruction::Type::JMPF, m_RegisterStack.top(), 0); + m_RegisterStack.pop(); + e->GetBody()->Accept(*this); + e->GetIteration()->Accept(*this); + PushInstruction(Instruction::Type::JMP, compareAddress); + m_Code[endAddress].Number = (double)m_Code.size(); } void ByteCodeGenerator::Visit(IdentifierExpression* e) @@ -237,18 +295,12 @@ void ByteCodeGenerator::Visit(IdentifierExpression* e) void ByteCodeGenerator::Visit(LiteralNumber* e) { - Instruction current; - IPLString regName = IPLString("const"); regName += std::to_string(m_RegisterTable.size()); m_RegisterTable.push_back(regName); m_RegisterStack.push(regName); - current.Descriptor = Instruction::Type::CONST; - current.Args[0] = regName; - current.Number = e->GetValue(); - - m_Code.push_back(current); + PushInstruction(Instruction::Type::CONST, regName, (size_t)e->GetValue()); } unsigned ByteCodeGenerator::ResolveRegisterName(IPLString& name) @@ -433,7 +485,7 @@ IPLString ByteCodeGenerator::GetCode() } ++programCounter; } - + result += std::to_string(programCounter) + ": "; result += "halt\n"; return result; } diff --git a/JSImpl/src/main.cpp b/JSImpl/src/main.cpp index b2fb83d..c15458e 100644 --- a/JSImpl/src/main.cpp +++ b/JSImpl/src/main.cpp @@ -67,8 +67,8 @@ void Generate() { IPLVector tokens; //Tokenize("var a = 0; var b = a + 123;a+b;", tokens); - Tokenize("var a; if(a < 4) { a = 8;} else { a = 2} ", tokens); - + /*Tokenize("var a; if(a < 4) { a = 8; if(a < 7) {var b = 4;}} else { a = 2} ", tokens);*/ + Tokenize("var i = 0; for (var j = 0; j < 10; j = j + 1) { i = i + j; }", tokens); std::cout << GenerateByteCode(Parse(tokens)); } -- cgit v1.3.1-23-gd82d From 637077d60045c97e4de1638146adf5e6ad88cb77 Mon Sep 17 00:00:00 2001 From: NDobrev Date: Thu, 15 Nov 2018 11:42:27 +0200 Subject: Fix ending --- JSImpl/src/ByteCodeGenerator.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'JSImpl/src/ByteCodeGenerator.cpp') diff --git a/JSImpl/src/ByteCodeGenerator.cpp b/JSImpl/src/ByteCodeGenerator.cpp index fefed78..09901e1 100644 --- a/JSImpl/src/ByteCodeGenerator.cpp +++ b/JSImpl/src/ByteCodeGenerator.cpp @@ -82,7 +82,9 @@ private: IPLVector m_Code; IPLStack m_RegisterStack; - unsigned m_CurrentStackPointer; IPLString m_OutputCode; }; + unsigned m_CurrentStackPointer; + IPLString m_OutputCode; +}; size_t ByteCodeGenerator::PushInstruction(Instruction::Type opcode, IPLString& arg0, IPLString& arg1, IPLString& arg2) { -- cgit v1.3.1-23-gd82d