diff options
9 files changed, 192 insertions, 37 deletions
| -rw-r--r-- | JSImpl/src/ASTInterpreter.cpp | 9 | ||||
| -rw-r--r-- | JSImpl/src/ASTInterpreter.h | 2 | ||||
| -rw-r--r-- | JSImpl/src/ASTPrinter.cpp | 7 | ||||
| -rw-r--r-- | JSImpl/src/ByteCodeGenerator.cpp | 119 | ||||
| -rw-r--r-- | JSImpl/src/ExpressionDefinitions.h | 14 | ||||
| -rw-r--r-- | JSImpl/src/ExpressionVisitor.h | 6 | ||||
| -rw-r--r-- | JSImpl/src/ExpressionsFwd.h | 5 | ||||
| -rw-r--r-- | JSImpl/src/Parser.cpp | 47 | ||||
| -rw-r--r-- | JSImpl/src/main.cpp | 20 |
diff --git a/JSImpl/src/ASTInterpreter.cpp b/JSImpl/src/ASTInterpreter.cpp index f550da9..f56706a 100644 --- a/JSImpl/src/ASTInterpreter.cpp +++ b/JSImpl/src/ASTInterpreter.cpp @@ -240,6 +240,7 @@ public: } virtual void Visit(IdentifierExpression* e) override { m_LValue = m_Interpreter->ModifyVariable(e->GetName()); } + virtual void Visit(Call* e) override { e->GetObjectOrCall()->Accept(*this); } ASTInterpreter* m_Interpreter; ASTInterpreter::ValuePtr m_LValue; @@ -565,9 +566,13 @@ void ASTInterpreter::Visit(EmptyExpression* e) { NOT_IMPLEMENTED; } -void ASTInterpreter::Visit(CallExpression* e) +void ASTInterpreter::Visit(Call* e) { - NOT_IMPLEMENTED; + e->GetObjectOrCall()->Accept(*this); + if (e->GetMember()) + { + e->GetMember()->Accept(*this); + } } void ASTInterpreter::Print(Printer& p) diff --git a/JSImpl/src/ASTInterpreter.h b/JSImpl/src/ASTInterpreter.h index cce6108..0c2c776 100644 --- a/JSImpl/src/ASTInterpreter.h +++ b/JSImpl/src/ASTInterpreter.h @@ -38,7 +38,7 @@ public: virtual void Visit(FunctionDeclaration* e) override; virtual void Visit(TopStatements* e) override; virtual void Visit(EmptyExpression* e) override; - virtual void Visit(CallExpression* e) override; + virtual void Visit(Call* e) override; ValuePtr& ModifyVariable(const IPLString& name); bool HasVariable(const IPLString& name); diff --git a/JSImpl/src/ASTPrinter.cpp b/JSImpl/src/ASTPrinter.cpp index 8c5783f..4a05510 100644 --- a/JSImpl/src/ASTPrinter.cpp +++ b/JSImpl/src/ASTPrinter.cpp @@ -126,11 +126,14 @@ public: virtual void Visit(CaseStatement *) override; virtual void Visit(WhileStatement* e) override; virtual void Visit(ForStatement* e) override; + virtual void Visit(Break* e) override; + virtual void Visit(Continue* e) override; virtual void Visit(FunctionDeclaration* e) override; virtual void Visit(TopStatements* e) override; virtual void Visit(EmptyExpression* e) override; - virtual void Visit(CallExpression* e) override; - + virtual void Visit(Call* e) override; + virtual void Visit(MemberAccess* e) override; + void Print( const char* name, const ExpressionPtr& expr, bool isLast); void Print( const char* name, const IPLVector<ExpressionPtr>& list, bool isLast); void Print( const char* name, const IPLVector<IPLString>& list, bool isLast); 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) {
diff --git a/JSImpl/src/ExpressionDefinitions.h b/JSImpl/src/ExpressionDefinitions.h index 1fad948..33f13b3 100644 --- a/JSImpl/src/ExpressionDefinitions.h +++ b/JSImpl/src/ExpressionDefinitions.h @@ -79,8 +79,13 @@ MACRO(IPLVector<ExpressionPtr>, Values, IPLVector<ExpressionPtr>()) #define CALL_EXPRESSION_MEMBERS(MACRO)\ - MACRO(ExpressionPtr, Identifier, ExpressionPtr())\ - MACRO(ExpressionPtr, Arguments, ExpressionPtr()) + MACRO(ExpressionPtr, ObjectOrCall, ExpressionPtr())\ + MACRO(ExpressionPtr, Member, ExpressionPtr()) + +#define MEMBER_ACCESS_EXPRESSION_MEMBERS(MACRO)\ + MACRO(IPLString, Name, "") + +#define MEMBER_NO_MEMBERS(MACRO) #define EXPRESSION_DEFINITION_ITERATOR(MACRO)\ MACRO(LiteralNull, NO_MEMBERS)\ @@ -105,4 +110,7 @@ MACRO(FunctionDeclaration, FUNCTION_EXPRESSION_MEMBERS)\ MACRO(TopStatements, TOP_EXPRESSION_MEMBERS)\ MACRO(EmptyExpression, NO_MEMBERS)\ - MACRO(CallExpression, CALL_EXPRESSION_MEMBERS) + MACRO(Call, CALL_EXPRESSION_MEMBERS)\ + MACRO(MemberAccess, MEMBER_ACCESS_EXPRESSION_MEMBERS)\ + MACRO(Break, MEMBER_NO_MEMBERS)\ + MACRO(Continue, MEMBER_NO_MEMBERS) diff --git a/JSImpl/src/ExpressionVisitor.h b/JSImpl/src/ExpressionVisitor.h index a44f581..8fbab7d 100644 --- a/JSImpl/src/ExpressionVisitor.h +++ b/JSImpl/src/ExpressionVisitor.h @@ -26,10 +26,14 @@ public: virtual void Visit(CaseStatement *e) { (void)e; NOT_IMPLEMENTED; } virtual void Visit(WhileStatement* e) { (void)e; NOT_IMPLEMENTED; } virtual void Visit(ForStatement* e) { (void)e; NOT_IMPLEMENTED; } + virtual void Visit(Break* e) { (void)e; NOT_IMPLEMENTED; } + virtual void Visit(Continue* e) { (void)e; NOT_IMPLEMENTED; } virtual void Visit(FunctionDeclaration* e) { (void)e; NOT_IMPLEMENTED; } virtual void Visit(TopStatements* e) { (void)e; NOT_IMPLEMENTED; } virtual void Visit(EmptyExpression* e) { (void)e; NOT_IMPLEMENTED; } - virtual void Visit(CallExpression* e) { (void)e; NOT_IMPLEMENTED; } + virtual void Visit(Call* e) { (void)e; NOT_IMPLEMENTED; } + virtual void Visit(MemberAccess* e) { (void)e; NOT_IMPLEMENTED; } + virtual void Visit(Expression* e) { (void)e; NOT_IMPLEMENTED; } // Unkown case };
\ No newline at end of file diff --git a/JSImpl/src/ExpressionsFwd.h b/JSImpl/src/ExpressionsFwd.h index 38f9330..753167d 100644 --- a/JSImpl/src/ExpressionsFwd.h +++ b/JSImpl/src/ExpressionsFwd.h @@ -25,6 +25,9 @@ class ForStatement; class FunctionDeclaration; class TopStatements; class EmptyExpression; -class CallExpression; +class Call; +class MemberAccess; +class Break; +class Continue; using ExpressionPtr = IPLSharedPtr<Expression>; diff --git a/JSImpl/src/Parser.cpp b/JSImpl/src/Parser.cpp index bc4920f..4bc97ce 100644 --- a/JSImpl/src/Parser.cpp +++ b/JSImpl/src/Parser.cpp @@ -23,6 +23,7 @@ private: bool MatchOneOf(IPLVector<TokenType> types); bool Match(TokenType type); + bool Peek(TokenType type); ExpressionPtr RegularExpression(); ExpressionPtr ParenthesizedExpression(); ExpressionPtr PrimaryExpression(NormalType a); @@ -125,6 +126,11 @@ bool Parser::Match(TokenType type) return false; } +bool Parser::Peek(TokenType type) +{ + return type == m_Tokens[m_Current].Type; +} + ExpressionPtr Parser::RegularExpression() { return nullptr; @@ -383,23 +389,32 @@ ExpressionPtr Parser::LeftSideExpression(NormalType a) ExpressionPtr Parser::CallExpression(NormalType a) { ExpressionPtr result; + auto ss = Snapshot(); - if (result = PrimaryExpression(a)) + if (auto pe = PrimaryExpression(a)) { - return result; + result = IPLMakeSharePtr<Call>(pe); } - Restore(ss); - if (result = FullNewExpression()) + else { - return result; + Restore(ss); } - - if (result = CallExpressionHelper(a)) + if (auto fne = FullNewExpression()) { - return result; + result = IPLMakeSharePtr<::Call>(fne); } - // TODO error - return nullptr; + + ExpressionPtr right; + do + { + right = CallExpressionHelper(a); + if (right) + { + result = IPLMakeSharePtr<::Call>(result, right); + } + } while (right); + + return result; } ExpressionPtr Parser::CallExpressionHelper(NormalType a) @@ -420,9 +435,7 @@ ExpressionPtr Parser::CallExpressionHelper(NormalType a) { if (Match(TokenType::Identifier)) { - auto next = CallExpressionHelper(a); - // return meaningfull expr - return nullptr; + return IPLMakeSharePtr<MemberAccess>(Prev().Lexeme); } // TODO error return nullptr; @@ -991,10 +1004,8 @@ ExpressionPtr Parser::ContinueStatement() { if (Match(TokenType::Continue)) { - auto type = TokenType::Continue; ExpressionPtr expr = OptionalLabel(); - bool suffix = true; - return IPLMakeSharePtr<UnaryExpression>(expr, type, suffix); + return IPLMakeSharePtr<Continue>(); } return nullptr; } @@ -1003,10 +1014,8 @@ ExpressionPtr Parser::BreakStatement() { if (Match(TokenType::Break)) { - auto type = TokenType::Break; ExpressionPtr expr = OptionalLabel(); - bool suffix = true; - return IPLMakeSharePtr<UnaryExpression>(expr, type, suffix); + return IPLMakeSharePtr<Break>(); } return nullptr; } diff --git a/JSImpl/src/main.cpp b/JSImpl/src/main.cpp index 06421a7..aee465d 100644 --- a/JSImpl/src/main.cpp +++ b/JSImpl/src/main.cpp @@ -76,15 +76,16 @@ void Generate() { //Tokenize("var a = 0; var b = a + 123;a+b;", tokens); /*Tokenize("var a; if(a < 4) { a = 8; if(a < 7) {var b = 4;}} else { a = 2} ", tokens);*/ - IPLString source = "var i = 0; \n" - "for (var j = 0; j < 10; j++)\n" - "{\n" - " i = i + j;\n" - "}"; + //IPLString source = "var i = 0; \n" + // "for (var j = 0; j < 10; j++)\n" + // "{\n" + // " i = i + j;\n" + // "}"; + IPLString source = "var a = 5; do{ a--; if(a == 4) continue; }while(a != 0)\n"; auto tokens = Tokenize(source.c_str()).tokens; auto asmb = GenerateByteCode(Parse(tokens), source, - ByteCodeGeneratorOptions(ByteCodeGeneratorOptions::OptimizationsType::None, true)); + ByteCodeGeneratorOptions(ByteCodeGeneratorOptions::OptimizationsType::None, false)); //sets the color to intense red on blue background #if defined(_WIN32) @@ -231,13 +232,16 @@ private: int main(int argc, char* argv[]) { + (void)argv; + (void)argc; // You can try => // Working dir: $(ProjectDir) // Command arguments: --input ./../examples/code.js --output ./../examples/some.ast --ast - CammandLineApp cmd; - cmd.RunAsCommandLine(argc, argv); + //CammandLineApp cmd; + //cmd.RunAsCommandLine(argc, argv); //auto r = Tokenize("a#4", {true ,true}); //RunParseCalc(); + Generate(); #if defined(_WIN32) //std::system("pause"); #endif |
