Website Summary Files Commits Branches @commit @diff @stats
path: root / JSImpl / src
diff options
context:
space:
mode:
Commitd5cb498ba37949193fecafa8c1f15d70ade79515 (patch)
Author
 Dimitar Trendafilov <dimitar@coherent-labs.com>
2018-10-21 21:27:36 +0300
Committer
 Dimitar Trendafilov <dimitar@coherent-labs.com>
2018-10-24 19:43:48 +0300
Filesdbf7da8806366afa5d435ff6a3e9d1adf397aa77 /JSImpl/src
IPL-d5cb498ba37949193fecafa8c1f15d70ade79515.tar
IPL-d5cb498ba37949193fecafa8c1f15d70ade79515.tar.gz
IPL-d5cb498ba37949193fecafa8c1f15d70ade79515.zip
Parentd57561ef43c80fa6050e80f4876a45ba886818ff (diff)
Added a tree interpreter
3 files changed, 221 insertions, 1 deletions
-rw-r--r--JSImpl/src/ASTInterpreter.cpp154
-rw-r--r--JSImpl/src/ASTInterpreter.h44
-rw-r--r--JSImpl/src/main.cpp24
diff --git a/JSImpl/src/ASTInterpreter.cpp b/JSImpl/src/ASTInterpreter.cpp
new file mode 100644
index 0000000..7ce6d59
--- /dev/null
+++ b/JSImpl/src/ASTInterpreter.cpp
@@ -0,0 +1,154 @@
+#include "ASTInterpreter.h"
+#include "Expression.h"
+#include <cassert>
+#include <iostream>
+
+ASTInterpreter::ASTInterpreter()
+{}
+
+ASTInterpreter::~ASTInterpreter()
+{}
+
+ASTInterpreter::ValueStack ASTInterpreter::Run(Expression* program)
+{
+ program->Accept(*this);
+ ValueStack result;
+ m_Evaluation.swap(result);
+ return result;
+}
+
+void ASTInterpreter::RunExpression(const ExpressionPtr& e)
+{
+ if (e) {
+ e->Accept(*this);
+ }
+}
+
+bool ASTInterpreter::EvalToBool(const ExpressionPtr& e)
+{
+ e->Accept(*this);
+ auto result = m_Evaluation.top();
+ m_Evaluation.pop();
+ return result != 0.0;
+}
+
+#define NOT_IMPLEMENTED (void)e; assert(0 && "not-implemented")
+
+void ASTInterpreter::Visit(LiteralNull* e) {
+ NOT_IMPLEMENTED;
+}
+
+void ASTInterpreter::Visit(LiteralUndefined* e) {
+ NOT_IMPLEMENTED;
+}
+void ASTInterpreter::Visit(LiteralString* e) {
+ NOT_IMPLEMENTED;
+}
+
+void ASTInterpreter::Visit(LiteralNumber* e) {
+ m_Evaluation.push(e->GetValue());
+}
+void ASTInterpreter::Visit(LiteralBoolean* e) {
+ m_Evaluation.push(e->GetValue());
+}
+
+void ASTInterpreter::Visit(BinaryExpression* e) {
+ e->GetLeft()->Accept(*this);
+ e->GetRight()->Accept(*this);
+ auto right = m_Evaluation.top();
+ m_Evaluation.pop();
+
+ auto left = m_Evaluation.top();
+ m_Evaluation.pop();
+
+ switch (e->GetOperator()) {
+ case TokenType::Plus:
+ std::cout << "PLUS:" << left << ':' << right << std::endl;
+ m_Evaluation.push(left + right);
+ break;
+ case TokenType::Minus:
+ m_Evaluation.push(left - right);
+ break;
+ case TokenType::Star:
+ m_Evaluation.push(left * right);
+ break;
+ case TokenType::Division:
+ m_Evaluation.push(left / right);
+ break;
+ default:
+ NOT_IMPLEMENTED;
+ }
+}
+
+void ASTInterpreter::Visit(UnaryExpression* e) {
+ NOT_IMPLEMENTED;
+}
+
+void ASTInterpreter::Visit(IdentifierExpression* e) {
+ auto values = m_Variables.find(e->GetName());
+ if (values != m_Variables.end()) {
+ m_Evaluation.push(values->second.top());
+ } else {
+ throw "Not-defined";
+ }
+}
+void ASTInterpreter::Visit(ListExpression* e) {
+ for (const auto& stmt: e->GetValues()) {
+ stmt->Accept(*this);
+ }
+}
+
+void ASTInterpreter::Visit(VariableDefinitionExpression* e) {
+ e->GetValue()->Accept(*this);
+ m_Variables[e->GetName()].push(m_Evaluation.top());
+ m_Evaluation.pop();
+}
+
+void ASTInterpreter::Visit(BlockStatement* e) {
+ for (const auto& stmt: e->GetValues()) {
+ stmt->Accept(*this);
+ }
+}
+
+void ASTInterpreter::Visit(LabeledStatement* e) {
+ RunExpression(e->GetStatement());
+}
+
+void ASTInterpreter::Visit(IfStatement* e) {
+ if (EvalToBool(e->GetCondition())) {
+ RunExpression(e->GetIfStatement());
+ } else {
+ RunExpression(e->GetElseStatement());
+ }
+}
+
+void ASTInterpreter::Visit(SwitchStatement* e) { NOT_IMPLEMENTED;}
+void ASTInterpreter::Visit(CaseStatement *e) { NOT_IMPLEMENTED;}
+
+void ASTInterpreter::Visit(WhileStatement* e) {
+ if (e->GetDoWhile()) {
+ RunExpression(e->GetBody());
+ }
+ while (EvalToBool(e->GetCondition())) {
+ RunExpression(e->GetBody());
+ }
+}
+
+void ASTInterpreter::Visit(ForStatement* e) {
+ for (RunExpression(e->GetInitialization());
+ EvalToBool(e->GetCondition());
+ RunExpression(e->GetIteration())) {
+ RunExpression(e->GetBody());
+ }
+}
+
+void ASTInterpreter::Visit(FunctionDeclaration* e) { NOT_IMPLEMENTED;}
+void ASTInterpreter::Visit(TopStatements* e) {
+ for (const auto& stmt: e->GetValues()) {
+ stmt->Accept(*this);
+ }
+}
+
+void ASTInterpreter::Visit(EmptyExpression* e) {
+ NOT_IMPLEMENTED;
+}
diff --git a/JSImpl/src/ASTInterpreter.h b/JSImpl/src/ASTInterpreter.h
new file mode 100644
index 0000000..1ffecde
--- /dev/null
+++ b/JSImpl/src/ASTInterpreter.h
@@ -0,0 +1,44 @@
+#pragma once
+
+#include "ExpressionVisitor.h"
+#include <stack>
+#include <string>
+#include <unordered_map>
+
+class ASTInterpreter : public ExpressionVisitor
+{
+public:
+ ASTInterpreter();
+ ~ASTInterpreter();
+
+ typedef double value_type;
+ typedef std::stack<value_type> ValueStack;
+
+ ValueStack Run(Expression* program);
+
+ virtual void Visit(LiteralNull* e) override;
+ virtual void Visit(LiteralUndefined* e) override;
+ virtual void Visit(LiteralString* e) override;
+ virtual void Visit(LiteralNumber* e) override;
+ virtual void Visit(LiteralBoolean* e) override;
+ virtual void Visit(BinaryExpression* e) override;
+ virtual void Visit(UnaryExpression* e) override;
+ virtual void Visit(IdentifierExpression* e) override;
+ virtual void Visit(ListExpression* e) override;
+ virtual void Visit(VariableDefinitionExpression* e) override;
+ virtual void Visit(BlockStatement* e) override;
+ virtual void Visit(LabeledStatement* e) override;
+ virtual void Visit(IfStatement* e) override;
+ virtual void Visit(SwitchStatement* e) override;
+ virtual void Visit(CaseStatement *) override;
+ virtual void Visit(WhileStatement* e) override;
+ virtual void Visit(ForStatement* e) override;
+ virtual void Visit(FunctionDeclaration* e) override;
+ virtual void Visit(TopStatements* e) override;
+ virtual void Visit(EmptyExpression* e) override;
+private:
+ void RunExpression(const ExpressionPtr& e);
+ bool EvalToBool(const ExpressionPtr& e);
+ ValueStack m_Evaluation;
+ std::unordered_map<std::string, ValueStack> m_Variables;
+};
diff --git a/JSImpl/src/main.cpp b/JSImpl/src/main.cpp
index 73f883f..80dcd32 100644
--- a/JSImpl/src/main.cpp
+++ b/JSImpl/src/main.cpp
@@ -1,6 +1,7 @@
#include "Lexer.h"
#include "Parser.h"
#include "ASTPrinter.h"
+#include "ASTInterpreter.h"
#include <iostream>
#define LOG(msg) std::cout << msg << std::endl
#define EXECUTE_TEST(test) std::cout << #test << " "; test();
@@ -198,6 +199,26 @@ void TestParseUnaryExpr()
expr->Accept(p);
}
+void RunParseCalc()
+{
+ IPLVector<Token> tokens;
+ //Tokenize("var a = 0; var b = a + 123;a+b;", tokens);
+ Tokenize("123 + 321", tokens);
+
+ // TODO make actual test :D
+ auto expr = Parse(tokens);
+ ASTPrinter p(std::cout);
+ expr->Accept(p);
+ ASTInterpreter i;
+ std::cout << "Running" << std::endl;
+ auto result = i.Run(expr.get());
+ std::cout << "Stack after run, top to bottom:" << std::endl;
+ while (!result.empty()) {
+ std::cout << result.top() << std::endl;
+ result.pop();
+ }
+}
+
void TestHexNumber()
{
IPLVector<Token> tokens;
@@ -235,7 +256,8 @@ int main()
EXECUTE_TEST(TestHexNumber);
EXECUTE_TEST(TestScientificNotationNumber);
- // TestParseUnaryExpr();
+ //TestParseUnaryExpr();
+ //RunParseCalc();
#if defined(_WIN32)
std::system("pause");
#endif