Website Summary Files Commits Branches @commit @diff @stats
path: root / JSImpl / src
diff options
context:
space:
mode:
Commit6c2f7812f65b4a5c60f85297d1bc4f918e32936e (patch)
Author
 martin dobrev <martindobrev0@gmail.com>
2018-11-03 14:47:20 +0200
Committer
 martin dobrev <martindobrev0@gmail.com>
2018-11-03 14:47:20 +0200
Files58a4ea3aba9ed7664908eff465aafd647c274124 /JSImpl/src
IPL-6c2f7812f65b4a5c60f85297d1bc4f918e32936e.tar
IPL-6c2f7812f65b4a5c60f85297d1bc4f918e32936e.tar.gz
IPL-6c2f7812f65b4a5c60f85297d1bc4f918e32936e.zip
Parent4e7231b52c36fdff699f8d3afd973c184854fdea (diff)
Introduce interactive interpreter.
4 files changed, 192 insertions, 129 deletions
-rw-r--r--JSImpl/src/ASTInterpreter.cpp265
-rw-r--r--JSImpl/src/ASTInterpreter.h8
-rw-r--r--JSImpl/src/Parser.cpp9
-rw-r--r--JSImpl/src/main.cpp39
diff --git a/JSImpl/src/ASTInterpreter.cpp b/JSImpl/src/ASTInterpreter.cpp
index cf078a7..138d94c 100644
--- a/JSImpl/src/ASTInterpreter.cpp
+++ b/JSImpl/src/ASTInterpreter.cpp
@@ -9,91 +9,91 @@
struct LValueExtractor : public ExpressionVisitor
{
public:
- LValueExtractor(ASTInterpreter* interpreter)
- : m_Interpreter(interpreter)
- {}
- ~LValueExtractor() {}
+ LValueExtractor(ASTInterpreter* interpreter)
+ : m_Interpreter(interpreter)
+ {}
+ ~LValueExtractor() {}
- ASTInterpreter::value_type* Run(Expression* program)
- {
- m_LValue = nullptr;
- program->Accept(*this);
- return m_LValue;
- }
+ ASTInterpreter::value_type* Run(Expression* program)
+ {
+ m_LValue = nullptr;
+ program->Accept(*this);
+ return m_LValue;
+ }
- virtual void Visit(LiteralNull* e) override { NOT_IMPLEMENTED; }
- virtual void Visit(LiteralUndefined* e) override { NOT_IMPLEMENTED; }
- virtual void Visit(LiteralString* e) override { NOT_IMPLEMENTED; }
- virtual void Visit(LiteralNumber* e) override { NOT_IMPLEMENTED; }
- virtual void Visit(LiteralBoolean* e) override { NOT_IMPLEMENTED; }
- virtual void Visit(LiteralObject* e) override { NOT_IMPLEMENTED; }
- virtual void Visit(BinaryExpression* e) override { NOT_IMPLEMENTED; }
- virtual void Visit(UnaryExpression* e) override { NOT_IMPLEMENTED; }
- virtual void Visit(IdentifierExpression* e) override { m_LValue = &m_Interpreter->ModifyVariable(e->GetName()); }
- virtual void Visit(ListExpression* e) override { NOT_IMPLEMENTED; }
- virtual void Visit(VariableDefinitionExpression* e) override { NOT_IMPLEMENTED; }
- virtual void Visit(BlockStatement* e) override { NOT_IMPLEMENTED; }
- virtual void Visit(LabeledStatement* e) override { NOT_IMPLEMENTED; }
- virtual void Visit(IfStatement* e) override { NOT_IMPLEMENTED; }
- virtual void Visit(SwitchStatement* e) override { NOT_IMPLEMENTED; }
- virtual void Visit(CaseStatement *e) override { NOT_IMPLEMENTED; }
- virtual void Visit(WhileStatement* e) override { NOT_IMPLEMENTED; }
- virtual void Visit(ForStatement* e) override { NOT_IMPLEMENTED; }
- virtual void Visit(FunctionDeclaration* e) override { NOT_IMPLEMENTED; }
- virtual void Visit(TopStatements* e) override { NOT_IMPLEMENTED; }
- virtual void Visit(EmptyExpression* e) override { NOT_IMPLEMENTED; }
- virtual void Visit(CallExpression* e) override { NOT_IMPLEMENTED; }
+ virtual void Visit(LiteralNull* e) override { NOT_IMPLEMENTED; }
+ virtual void Visit(LiteralUndefined* e) override { NOT_IMPLEMENTED; }
+ virtual void Visit(LiteralString* e) override { NOT_IMPLEMENTED; }
+ virtual void Visit(LiteralNumber* e) override { NOT_IMPLEMENTED; }
+ virtual void Visit(LiteralBoolean* e) override { NOT_IMPLEMENTED; }
+ virtual void Visit(LiteralObject* e) override { NOT_IMPLEMENTED; }
+ virtual void Visit(BinaryExpression* e) override { NOT_IMPLEMENTED; }
+ virtual void Visit(UnaryExpression* e) override { NOT_IMPLEMENTED; }
+ virtual void Visit(IdentifierExpression* e) override { m_LValue = &m_Interpreter->ModifyVariable(e->GetName()); }
+ virtual void Visit(ListExpression* e) override { NOT_IMPLEMENTED; }
+ virtual void Visit(VariableDefinitionExpression* e) override { NOT_IMPLEMENTED; }
+ virtual void Visit(BlockStatement* e) override { NOT_IMPLEMENTED; }
+ virtual void Visit(LabeledStatement* e) override { NOT_IMPLEMENTED; }
+ virtual void Visit(IfStatement* e) override { NOT_IMPLEMENTED; }
+ virtual void Visit(SwitchStatement* e) override { NOT_IMPLEMENTED; }
+ virtual void Visit(CaseStatement *e) override { NOT_IMPLEMENTED; }
+ virtual void Visit(WhileStatement* e) override { NOT_IMPLEMENTED; }
+ virtual void Visit(ForStatement* e) override { NOT_IMPLEMENTED; }
+ virtual void Visit(FunctionDeclaration* e) override { NOT_IMPLEMENTED; }
+ virtual void Visit(TopStatements* e) override { NOT_IMPLEMENTED; }
+ virtual void Visit(EmptyExpression* e) override { NOT_IMPLEMENTED; }
+ virtual void Visit(CallExpression* e) override { NOT_IMPLEMENTED; }
- ASTInterpreter* m_Interpreter;
- ASTInterpreter::value_type* m_LValue;
+ ASTInterpreter* m_Interpreter;
+ ASTInterpreter::value_type* m_LValue;
};
struct VariableScope
{
- VariableScope(ASTInterpreter* interpreter)
- : m_Interpreter(interpreter)
- {
- m_Interpreter->EnterScope();
- }
+ VariableScope(ASTInterpreter* interpreter)
+ : m_Interpreter(interpreter)
+ {
+ m_Interpreter->EnterScope();
+ }
- ~VariableScope() {
- m_Interpreter->LeaveScope();
- }
+ ~VariableScope() {
+ m_Interpreter->LeaveScope();
+ }
- VariableScope(VariableScope&) = delete;
- VariableScope(VariableScope&&) = delete;
- VariableScope& operator=(VariableScope&) = delete;
- VariableScope& operator=(VariableScope&&) = delete;
+ VariableScope(VariableScope&) = delete;
+ VariableScope(VariableScope&&) = delete;
+ VariableScope& operator=(VariableScope&) = delete;
+ VariableScope& operator=(VariableScope&&) = delete;
- ASTInterpreter* m_Interpreter;
+ ASTInterpreter* m_Interpreter;
};
struct StackScope
{
- StackScope(ASTInterpreter* interpreter)
- : m_Interpreter(interpreter)
+ StackScope(ASTInterpreter* interpreter)
+ : m_Interpreter(interpreter)
, m_StackSize(m_Interpreter->m_Evaluation.size())
- {
- }
+ {
+ }
- ~StackScope() {
- m_Interpreter->m_Evaluation.resize(m_StackSize);
- }
+ ~StackScope() {
+ m_Interpreter->m_Evaluation.resize(m_StackSize);
+ }
- StackScope(StackScope&) = delete;
- StackScope(StackScope&&) = delete;
- StackScope& operator=(StackScope&) = delete;
- StackScope& operator=(StackScope&&) = delete;
+ StackScope(StackScope&) = delete;
+ StackScope(StackScope&&) = delete;
+ StackScope& operator=(StackScope&) = delete;
+ StackScope& operator=(StackScope&&) = delete;
- ASTInterpreter* m_Interpreter;
+ ASTInterpreter* m_Interpreter;
size_t m_StackSize;
};
ASTInterpreter::ASTInterpreter()
{
- // Allow globals
- EnterScope();
+ // Allow globals
+ EnterScope();
}
ASTInterpreter::~ASTInterpreter()
@@ -124,38 +124,38 @@ bool ASTInterpreter::EvalToBool(const ExpressionPtr& e)
void ASTInterpreter::EnterScope()
{
- m_Scopes.push(Scope{});
+ m_Scopes.push(Scope{});
}
void ASTInterpreter::LeaveScope()
{
- const auto& scope = m_Scopes.top();
- for (auto& var : scope) {
- auto values = m_Variables.find(var);
- values->second.pop_back();
- if (values->second.empty()) {
- m_Variables.erase(values);
- }
- }
- m_Scopes.pop();
+ const auto& scope = m_Scopes.top();
+ for (auto& var : scope) {
+ auto values = m_Variables.find(var);
+ values->second.pop_back();
+ if (values->second.empty()) {
+ m_Variables.erase(values);
+ }
+ }
+ m_Scopes.pop();
}
ASTInterpreter::value_type& ASTInterpreter::ModifyVariable(const IPLString& name)
{
- auto values = m_Variables.find(name);
- if (values != m_Variables.end()) {
- return values->second.back();
- }
- else {
- assert(0 && "not-defined");
- }
- static value_type undefined;
- return undefined;
+ auto values = m_Variables.find(name);
+ if (values != m_Variables.end()) {
+ return values->second.back();
+ }
+ else {
+ assert(0 && "not-defined");
+ }
+ static value_type undefined;
+ return undefined;
}
bool ASTInterpreter::HasVariable(const IPLString& name)
{
- return m_Variables.find(name) != m_Variables.end();
+ return m_Variables.find(name) != m_Variables.end();
}
void ASTInterpreter::Visit(LiteralNull* e) {
@@ -203,46 +203,53 @@ void ASTInterpreter::Visit(BinaryExpression* e) {
case TokenType::Division:
m_Evaluation.push_back(left / right);
break;
- case TokenType::Less:
- m_Evaluation.push_back(left < right);
- break;
- case TokenType::Comma:
- m_Evaluation.push_back(right);
- break;
- case TokenType::EqualEqual:
- m_Evaluation.push_back(fabs(left - right) < 0.0001);
- break;
+ case TokenType::Less:
+ m_Evaluation.push_back(left < right);
+ break;
+ case TokenType::Comma:
+ m_Evaluation.push_back(right);
+ break;
+ case TokenType::EqualEqual:
+ m_Evaluation.push_back(fabs(left - right) < 0.0001);
+ break;
+ case TokenType::Equal:
+ {
+ LValueExtractor extractor(this);
+ auto lvalue = extractor.Run(e->GetLeft().get());
+ *lvalue = right;
+ }
+ break;
default:
NOT_IMPLEMENTED;
}
}
void ASTInterpreter::Visit(UnaryExpression* e) {
- LValueExtractor extractor(this);
- auto lvalue = extractor.Run(e->GetExpr().get());
- if (e->GetSuffix())
- {
- m_Evaluation.push_back(*lvalue);
- }
- switch (e->GetOperator())
- {
- case TokenType::PlusPlus:
- ++(*lvalue);
- break;
- case TokenType::MinusMinus:
- --(*lvalue);
- break;
- default:
- NOT_IMPLEMENTED;
- }
- if (!e->GetSuffix())
- {
- m_Evaluation.push_back(*lvalue);
- }
+ LValueExtractor extractor(this);
+ auto lvalue = extractor.Run(e->GetExpr().get());
+ if (e->GetSuffix())
+ {
+ m_Evaluation.push_back(*lvalue);
+ }
+ switch (e->GetOperator())
+ {
+ case TokenType::PlusPlus:
+ ++(*lvalue);
+ break;
+ case TokenType::MinusMinus:
+ --(*lvalue);
+ break;
+ default:
+ NOT_IMPLEMENTED;
+ }
+ if (!e->GetSuffix())
+ {
+ m_Evaluation.push_back(*lvalue);
+ }
}
void ASTInterpreter::Visit(IdentifierExpression* e) {
- m_Evaluation.push_back(ModifyVariable(e->GetName()));
+ m_Evaluation.push_back(ModifyVariable(e->GetName()));
}
void ASTInterpreter::Visit(ListExpression* e) {
@@ -253,9 +260,9 @@ void ASTInterpreter::Visit(ListExpression* e) {
void ASTInterpreter::Visit(VariableDefinitionExpression* e) {
e->GetValue()->Accept(*this);
- auto& name = e->GetName();
+ auto& name = e->GetName();
m_Variables[name].push_back(m_Evaluation.back());
- m_Scopes.top().push_back(name);
+ m_Scopes.top().push_back(name);
m_Evaluation.pop_back();
}
@@ -270,13 +277,13 @@ void ASTInterpreter::Visit(LabeledStatement* e) {
}
void ASTInterpreter::Visit(IfStatement* e) {
- VariableScope scope(this);
- if (EvalToBool(e->GetCondition())) {
- VariableScope ifScope(this);
- RunExpression(e->GetIfStatement());
+ VariableScope scope(this);
+ if (EvalToBool(e->GetCondition())) {
+ VariableScope ifScope(this);
+ RunExpression(e->GetIfStatement());
} else {
- VariableScope elseScope(this);
- RunExpression(e->GetElseStatement());
+ VariableScope elseScope(this);
+ RunExpression(e->GetElseStatement());
}
}
@@ -284,19 +291,19 @@ void ASTInterpreter::Visit(SwitchStatement* e) { NOT_IMPLEMENTED;}
void ASTInterpreter::Visit(CaseStatement *e) { NOT_IMPLEMENTED;}
void ASTInterpreter::Visit(WhileStatement* e) {
- VariableScope scope(this);
+ VariableScope scope(this);
if (e->GetDoWhile()) {
- VariableScope bodyScope(this);
+ VariableScope bodyScope(this);
RunExpression(e->GetBody());
}
while (EvalToBool(e->GetCondition())) {
- VariableScope bodyScope(this);
+ VariableScope bodyScope(this);
RunExpression(e->GetBody());
}
}
void ASTInterpreter::Visit(ForStatement* e) {
- VariableScope scope(this);
+ VariableScope scope(this);
{
StackScope stackScope(this);
@@ -328,5 +335,13 @@ void ASTInterpreter::Visit(EmptyExpression* e) {
void ASTInterpreter::Visit(CallExpression* e)
{
- NOT_IMPLEMENTED;
+ NOT_IMPLEMENTED;
}
+
+void ASTInterpreter::Print(Printer& p)
+{
+ for (auto& it : m_Variables)
+ {
+ p.PrintVariable(it.first.c_str(), ModifyVariable(it.first));
+ }
+} \ No newline at end of file
diff --git a/JSImpl/src/ASTInterpreter.h b/JSImpl/src/ASTInterpreter.h
index 4683d63..cde3dd0 100644
--- a/JSImpl/src/ASTInterpreter.h
+++ b/JSImpl/src/ASTInterpreter.h
@@ -41,6 +41,14 @@ public:
value_type& ModifyVariable(const IPLString& name);
bool HasVariable(const IPLString& name);
+
+ class Printer
+ {
+ public:
+ virtual void PrintVariable(const char* name, double value) = 0;
+ };
+
+ void Print(Printer& p);
private:
void RunExpression(const ExpressionPtr& e);
bool EvalToBool(const ExpressionPtr& e);
diff --git a/JSImpl/src/Parser.cpp b/JSImpl/src/Parser.cpp
index b0d394b..8c387c8 100644
--- a/JSImpl/src/Parser.cpp
+++ b/JSImpl/src/Parser.cpp
@@ -470,9 +470,10 @@ ExpressionPtr Parser::Unary()
TokenType::Bang,
}))
{
+ auto type = Prev().Type;
auto ls = Unary();
auto suffix = false;
- return IPLMakeSharePtr<UnaryExpression>(ls, Prev().Type, suffix);
+ return IPLMakeSharePtr<UnaryExpression>(ls, type, suffix);
}
else
{
@@ -662,8 +663,9 @@ ExpressionPtr Parser::AssignmentExpression()
TokenType::BitwiseXorEqual,
TokenType::BitwiseOrEqual }))
{
+ auto type = Prev().Type;
auto right = AssignmentExpression();
- return IPLMakeSharePtr<BinaryExpression>(left, right, Prev().Type);
+ return IPLMakeSharePtr<BinaryExpression>(left, right, type);
}
// revert state;
m_Current = snapShot;
@@ -675,10 +677,11 @@ ExpressionPtr Parser::Expression()
auto ae = AssignmentExpression();
while (Match(TokenType::Comma))
{
+ auto type = Prev().Type;
auto next = AssignmentExpression();
if (next)
{
- ae = IPLMakeSharePtr<BinaryExpression>(ae, next, Prev().Type);
+ ae = IPLMakeSharePtr<BinaryExpression>(ae, next, type);
}
else
{
diff --git a/JSImpl/src/main.cpp b/JSImpl/src/main.cpp
index 0d78a10..f3eb90a 100644
--- a/JSImpl/src/main.cpp
+++ b/JSImpl/src/main.cpp
@@ -25,9 +25,46 @@ void RunParseCalc()
std::cout << "S = " << i.ModifyVariable("a") << std::endl;
}
+class InterpreterPrinter : public ASTInterpreter::Printer
+{
+public:
+ virtual void PrintVariable(const char* name, double value) override
+ {
+ std::cout << name << ": " << value << std::endl;
+ }
+};
+
+void InteractiveInterpreter()
+{
+ char command[1000];
+ ASTInterpreter i;
+ InterpreterPrinter p;
+ do
+ {
+ std::cin.getline(command, 1000);
+ if (strcmp(command, "exit") == 0)
+ {
+ break;
+ }
+ if (strcmp(command, "print") == 0)
+ {
+ i.Print(p);
+ continue;
+ }
+ IPLVector<Token> tokens;
+ Tokenize(command, tokens);
+ auto result = i.Run(Parse(tokens).get());
+ while (!result.empty()) {
+ std::cout << result.back() << std::endl;
+ result.pop_back();
+ }
+ } while (true);
+}
+
int main()
{
- RunParseCalc();
+ //RunParseCalc();
+ InteractiveInterpreter();
#if defined(_WIN32)
std::system("pause");