From 70a7bd82774843a5750fb96c0d7e51553505811c Mon Sep 17 00:00:00 2001 From: Dimitar Trendafilov Date: Sun, 1 Nov 2020 20:39:33 +0200 Subject: Move value in ASTInterpreter to be shared pointer --- JSImpl/src/ASTInterpreter.cpp | 77 ++++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 30 deletions(-) (limited to 'JSImpl/src/ASTInterpreter.cpp') diff --git a/JSImpl/src/ASTInterpreter.cpp b/JSImpl/src/ASTInterpreter.cpp index 9874a4d..d5017aa 100644 --- a/JSImpl/src/ASTInterpreter.cpp +++ b/JSImpl/src/ASTInterpreter.cpp @@ -6,6 +6,21 @@ #undef NOT_IMPLEMENTED #define NOT_IMPLEMENTED (void)e; assert(0 && "not-implemented") +namespace +{ + template + ASTInterpreter::value_type MakeValue(T&& v) + { + return IPLMakeSharePtr(v); + } + + template + ASTInterpreter::value_type MakeValue(const T& v) + { + return IPLMakeSharePtr(v); + } +} + struct LValueExtractor : public ExpressionVisitor { public: @@ -14,17 +29,17 @@ public: {} ~LValueExtractor() {} - ASTInterpreter::value_type* Run(Expression* program) + ASTInterpreter::value_type Run(Expression* program) { m_LValue = nullptr; program->Accept(*this); return m_LValue; } - virtual void Visit(IdentifierExpression* e) override { m_LValue = &m_Interpreter->ModifyVariable(e->GetName()); } + virtual void Visit(IdentifierExpression* e) override { m_LValue = m_Interpreter->ModifyVariable(e->GetName()); } ASTInterpreter* m_Interpreter; - ASTInterpreter::value_type* m_LValue; + ASTInterpreter::value_type m_LValue; }; @@ -98,7 +113,7 @@ bool ASTInterpreter::EvalToBool(const ExpressionPtr& e) e->Accept(*this); auto result = m_Evaluation.back(); m_Evaluation.pop_back(); - return result != 0.0; + return *result != 0.0; } void ASTInterpreter::EnterScope() @@ -154,54 +169,54 @@ void ASTInterpreter::Visit(LiteralObject* e) } void ASTInterpreter::Visit(LiteralNumber* e) { - m_Evaluation.push_back(e->GetValue()); + m_Evaluation.push_back(MakeValue(e->GetValue())); } void ASTInterpreter::Visit(LiteralBoolean* e) { - m_Evaluation.push_back(e->GetValue()); + m_Evaluation.push_back(MakeValue(e->GetValue())); } void ASTInterpreter::Visit(BinaryExpression* e) { e->GetLeft()->Accept(*this); e->GetRight()->Accept(*this); - auto right = m_Evaluation.back(); + auto right = *m_Evaluation.back(); m_Evaluation.pop_back(); - auto left = m_Evaluation.back(); + auto left = *m_Evaluation.back(); m_Evaluation.pop_back(); switch (e->GetOperator()) { case TokenType::Plus: - m_Evaluation.push_back(left + right); + m_Evaluation.push_back(MakeValue(left + right)); break; case TokenType::Minus: - m_Evaluation.push_back(left - right); + m_Evaluation.push_back(MakeValue(left - right)); break; case TokenType::Star: - m_Evaluation.push_back(left * right); + m_Evaluation.push_back(MakeValue(left * right)); break; case TokenType::Division: - m_Evaluation.push_back(left / right); + m_Evaluation.push_back(MakeValue(left / right)); break; case TokenType::Less: - m_Evaluation.push_back(left < right); + m_Evaluation.push_back(MakeValue(left < right)); + break; + case TokenType::LessEqual: + m_Evaluation.push_back(MakeValue(left <= right)); + break; + case TokenType::Greater: + m_Evaluation.push_back(MakeValue(left > right)); + break; + case TokenType::GreaterEqual: + m_Evaluation.push_back(MakeValue(left >= right)); break; - case TokenType::LessEqual: - m_Evaluation.push_back(left <= right); - break; - case TokenType::Greater: - m_Evaluation.push_back(left > right); - break; - case TokenType::GreaterEqual: - m_Evaluation.push_back(left >= right); - break; case TokenType::Comma: - m_Evaluation.push_back(right); + m_Evaluation.push_back(MakeValue(std::move(right))); break; case TokenType::EqualEqual: - m_Evaluation.push_back(fabs(left - right) < 0.0001); + m_Evaluation.push_back(MakeValue(fabs(left - right) < 0.0001)); break; case TokenType::BangEqual: - m_Evaluation.push_back(fabs(left - right) > 0.0001); + m_Evaluation.push_back(MakeValue(fabs(left - right) > 0.0001)); break; case TokenType::Equal: { @@ -221,7 +236,9 @@ void ASTInterpreter::Visit(UnaryExpression* e) { case TokenType::Minus: { e->GetExpr()->Accept(*this); - m_Evaluation.back() *= -1; + auto v = m_Evaluation.back(); + m_Evaluation.pop_back(); + m_Evaluation.push_back(MakeValue(-(*v))); break; } case TokenType::Plus: @@ -236,12 +253,12 @@ void ASTInterpreter::Visit(UnaryExpression* e) { auto lvalue = extractor.Run(e->GetExpr().get()); if (e->GetSuffix()) { - m_Evaluation.push_back(*lvalue); + m_Evaluation.push_back(MakeValue(*lvalue)); } *lvalue += e->GetOperator() == TokenType::PlusPlus ? 1 : -1; if (!e->GetSuffix()) { - m_Evaluation.push_back(*lvalue); + m_Evaluation.push_back(MakeValue(*lvalue)); } break; } @@ -347,6 +364,6 @@ void ASTInterpreter::Print(Printer& p) { for (auto& it : m_Variables) { - p.PrintVariable(it.first.c_str(), ModifyVariable(it.first)); + p.PrintVariable(it.first.c_str(), *ModifyVariable(it.first)); } -} \ No newline at end of file +} -- cgit v1.3.1-23-gd82d From b93662dbcc9d30c69cce7d1342606cafc60bb3f0 Mon Sep 17 00:00:00 2001 From: Dimitar Trendafilov Date: Sun, 1 Nov 2020 20:48:23 +0200 Subject: Fix name of ASTInterpreter value type --- JSImpl/src/ASTInterpreter.cpp | 12 ++++++------ JSImpl/src/ASTInterpreter.h | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'JSImpl/src/ASTInterpreter.cpp') diff --git a/JSImpl/src/ASTInterpreter.cpp b/JSImpl/src/ASTInterpreter.cpp index d5017aa..ae0d2b5 100644 --- a/JSImpl/src/ASTInterpreter.cpp +++ b/JSImpl/src/ASTInterpreter.cpp @@ -9,13 +9,13 @@ namespace { template - ASTInterpreter::value_type MakeValue(T&& v) + ASTInterpreter::ValuePtr MakeValue(T&& v) { return IPLMakeSharePtr(v); } template - ASTInterpreter::value_type MakeValue(const T& v) + ASTInterpreter::ValuePtr MakeValue(const T& v) { return IPLMakeSharePtr(v); } @@ -29,7 +29,7 @@ public: {} ~LValueExtractor() {} - ASTInterpreter::value_type Run(Expression* program) + ASTInterpreter::ValuePtr Run(Expression* program) { m_LValue = nullptr; program->Accept(*this); @@ -39,7 +39,7 @@ public: virtual void Visit(IdentifierExpression* e) override { m_LValue = m_Interpreter->ModifyVariable(e->GetName()); } ASTInterpreter* m_Interpreter; - ASTInterpreter::value_type m_LValue; + ASTInterpreter::ValuePtr m_LValue; }; @@ -134,7 +134,7 @@ void ASTInterpreter::LeaveScope() m_Scopes.pop(); } -ASTInterpreter::value_type& ASTInterpreter::ModifyVariable(const IPLString& name) +ASTInterpreter::ValuePtr& ASTInterpreter::ModifyVariable(const IPLString& name) { auto values = m_Variables.find(name); if (values != m_Variables.end()) { @@ -143,7 +143,7 @@ ASTInterpreter::value_type& ASTInterpreter::ModifyVariable(const IPLString& name else { assert(0 && "not-defined"); } - static value_type undefined; + static ValuePtr undefined; return undefined; } diff --git a/JSImpl/src/ASTInterpreter.h b/JSImpl/src/ASTInterpreter.h index 16aebfa..e8dae37 100644 --- a/JSImpl/src/ASTInterpreter.h +++ b/JSImpl/src/ASTInterpreter.h @@ -2,6 +2,8 @@ #include "ExpressionVisitor.h" +#include + class ASTInterpreter : public ExpressionVisitor { public: @@ -9,10 +11,8 @@ public: ~ASTInterpreter(); - // TODO: Changing this to a shared_ptr (or GC-enabled value*) will - // allow for much simpler implementation of all varible assignments. - typedef IPLSharedPtr value_type; - typedef IPLVector ValueStack; + typedef IPLSharedPtr ValuePtr; + typedef IPLVector ValueStack; ValueStack Run(Expression* program); @@ -39,7 +39,7 @@ public: virtual void Visit(EmptyExpression* e) override; virtual void Visit(CallExpression* e) override; - value_type& ModifyVariable(const IPLString& name); + ValuePtr& ModifyVariable(const IPLString& name); bool HasVariable(const IPLString& name); class Printer -- cgit v1.3.1-23-gd82d From d8704c516b3a8b32817ffcad1868d7cd135efe48 Mon Sep 17 00:00:00 2001 From: Dimitar Trendafilov Date: Sun, 1 Nov 2020 21:34:40 +0200 Subject: Move AST interpreter value to std::variant --- JSImpl/solution/genie.lua | 2 +- JSImpl/src/ASTInterpreter.cpp | 161 +++++++++++++++++++++++++++++++++++++----- JSImpl/src/ASTInterpreter.h | 3 +- JSImpl/test/ParserTests.cpp | 52 +++++++------- 4 files changed, 174 insertions(+), 44 deletions(-) (limited to 'JSImpl/src/ASTInterpreter.cpp') diff --git a/JSImpl/solution/genie.lua b/JSImpl/solution/genie.lua index 247f72d..777446b 100644 --- a/JSImpl/solution/genie.lua +++ b/JSImpl/solution/genie.lua @@ -3,7 +3,7 @@ solution 'JSImpl' flags { 'FatalWarnings', 'ExtraWarnings', - 'Cpp14', + 'Cpp17', 'Symbols', } defines { diff --git a/JSImpl/src/ASTInterpreter.cpp b/JSImpl/src/ASTInterpreter.cpp index ae0d2b5..fd631ca 100644 --- a/JSImpl/src/ASTInterpreter.cpp +++ b/JSImpl/src/ASTInterpreter.cpp @@ -11,14 +11,135 @@ namespace template ASTInterpreter::ValuePtr MakeValue(T&& v) { - return IPLMakeSharePtr(v); + return IPLMakeSharePtr(v); } template ASTInterpreter::ValuePtr MakeValue(const T& v) { - return IPLMakeSharePtr(v); + return IPLMakeSharePtr(v); } + + struct ValueToBool + { + bool operator()(double d) const + { + return d != 0.0; + } + }; + + struct ValueAdd + { + ASTInterpreter::ValuePtr operator()(double l, double r) const + { + return MakeValue(l + r); + } + }; + + struct ValueMinus + { + ASTInterpreter::ValuePtr operator()(double l, double r) const + { + return MakeValue(l - r); + } + }; + struct ValueProduct + { + ASTInterpreter::ValuePtr operator()(double l, double r) const + { + return MakeValue(l * r); + } + }; + struct ValueDivide + { + ASTInterpreter::ValuePtr operator()(double l, double r) const + { + return MakeValue(l / r); + } + }; + struct ValueLess + { + ASTInterpreter::ValuePtr operator()(double l, double r) const + { + return MakeValue(l < r); + } + }; + struct ValueLessEqual + { + ASTInterpreter::ValuePtr operator()(double l, double r) const + { + return MakeValue(l <= r); + } + }; + struct ValueGreater + { + ASTInterpreter::ValuePtr operator()(double l, double r) const + { + return MakeValue(l > r); + } + }; + struct ValueGreaterEqual + { + ASTInterpreter::ValuePtr operator()(double l, double r) const + { + return MakeValue(l >= r); + } + }; + + struct ValueEqualEqual + { + ASTInterpreter::ValuePtr operator()(double left, double right) const + { + return MakeValue(fabs(left - right) <= 0.0001); + } + }; + + struct ValueBangEqual + { + ASTInterpreter::ValuePtr operator()(double left, double right) const + { + return MakeValue(fabs(left - right) > 0.0001); + } + }; + + struct ValueUnaryMinus + { + ASTInterpreter::ValuePtr operator()(double v) const + { + return MakeValue(-v); + } + }; + struct ValueIncrement + { + void operator()(double& v) const + { + v += 1; + } + }; + + struct ValueDecrement + { + void operator()(double& v) const + { + v -= 1; + } + }; + + struct ValuePrint + { + ValuePrint(const char* name, ASTInterpreter::Printer* printer) + : Name(name) + , Printer(printer) + {} + + void operator()(double value) const + { + Printer->PrintVariable(Name, value); + } + + const char* Name; + ASTInterpreter::Printer* Printer; + }; } struct LValueExtractor : public ExpressionVisitor @@ -113,7 +234,7 @@ bool ASTInterpreter::EvalToBool(const ExpressionPtr& e) e->Accept(*this); auto result = m_Evaluation.back(); m_Evaluation.pop_back(); - return *result != 0.0; + return std::visit(ValueToBool(), *result); } void ASTInterpreter::EnterScope() @@ -186,37 +307,37 @@ void ASTInterpreter::Visit(BinaryExpression* e) { switch (e->GetOperator()) { case TokenType::Plus: - m_Evaluation.push_back(MakeValue(left + right)); + m_Evaluation.push_back(std::visit(ValueAdd(), left, right)); break; case TokenType::Minus: - m_Evaluation.push_back(MakeValue(left - right)); + m_Evaluation.push_back(std::visit(ValueMinus(), left, right)); break; case TokenType::Star: - m_Evaluation.push_back(MakeValue(left * right)); + m_Evaluation.push_back(std::visit(ValueProduct(), left, right)); break; case TokenType::Division: - m_Evaluation.push_back(MakeValue(left / right)); + m_Evaluation.push_back(std::visit(ValueDivide(), left, right)); break; case TokenType::Less: - m_Evaluation.push_back(MakeValue(left < right)); + m_Evaluation.push_back(std::visit(ValueLess(), left, right)); break; case TokenType::LessEqual: - m_Evaluation.push_back(MakeValue(left <= right)); + m_Evaluation.push_back(std::visit(ValueLessEqual(), left, right)); break; case TokenType::Greater: - m_Evaluation.push_back(MakeValue(left > right)); + m_Evaluation.push_back(std::visit(ValueGreater(), left, right)); break; case TokenType::GreaterEqual: - m_Evaluation.push_back(MakeValue(left >= right)); + m_Evaluation.push_back(std::visit(ValueGreaterEqual(), left, right)); break; case TokenType::Comma: m_Evaluation.push_back(MakeValue(std::move(right))); break; case TokenType::EqualEqual: - m_Evaluation.push_back(MakeValue(fabs(left - right) < 0.0001)); + m_Evaluation.push_back(std::visit(ValueEqualEqual(), left, right)); break; case TokenType::BangEqual: - m_Evaluation.push_back(MakeValue(fabs(left - right) > 0.0001)); + m_Evaluation.push_back(std::visit(ValueBangEqual(), left, right)); break; case TokenType::Equal: { @@ -238,7 +359,7 @@ void ASTInterpreter::Visit(UnaryExpression* e) { e->GetExpr()->Accept(*this); auto v = m_Evaluation.back(); m_Evaluation.pop_back(); - m_Evaluation.push_back(MakeValue(-(*v))); + m_Evaluation.push_back(std::visit(ValueUnaryMinus(), *v)); break; } case TokenType::Plus: @@ -255,7 +376,14 @@ void ASTInterpreter::Visit(UnaryExpression* e) { { m_Evaluation.push_back(MakeValue(*lvalue)); } - *lvalue += e->GetOperator() == TokenType::PlusPlus ? 1 : -1; + if (e->GetOperator() == TokenType::PlusPlus) + { + std::visit(ValueIncrement(), *lvalue); + } + else + { + std::visit(ValueDecrement(), *lvalue); + } if (!e->GetSuffix()) { m_Evaluation.push_back(MakeValue(*lvalue)); @@ -364,6 +492,7 @@ void ASTInterpreter::Print(Printer& p) { for (auto& it : m_Variables) { - p.PrintVariable(it.first.c_str(), *ModifyVariable(it.first)); + auto& value = ModifyVariable(it.first); + std::visit(ValuePrint(it.first.c_str(), &p), *value); } } diff --git a/JSImpl/src/ASTInterpreter.h b/JSImpl/src/ASTInterpreter.h index e8dae37..ba797c1 100644 --- a/JSImpl/src/ASTInterpreter.h +++ b/JSImpl/src/ASTInterpreter.h @@ -11,7 +11,8 @@ public: ~ASTInterpreter(); - typedef IPLSharedPtr ValuePtr; + typedef std::variant Value; + typedef IPLSharedPtr ValuePtr; typedef IPLVector ValueStack; ValueStack Run(Expression* program); diff --git a/JSImpl/test/ParserTests.cpp b/JSImpl/test/ParserTests.cpp index 31fa123..f47b4b3 100644 --- a/JSImpl/test/ParserTests.cpp +++ b/JSImpl/test/ParserTests.cpp @@ -27,7 +27,7 @@ TEST(Parser, VariableDeclaration) ASTInterpreter i; i.Run(expr.get()); ASSERT_TRUE(i.HasVariable("s")); - ASSERT_TRUE(*i.ModifyVariable("s") == 0.0); + ASSERT_TRUE(std::get(*i.ModifyVariable("s")) == 0.0); } TEST(Parser, Assignment) @@ -38,7 +38,7 @@ TEST(Parser, Assignment) ASTInterpreter i; i.Run(expr.get()); ASSERT_TRUE(i.HasVariable("s")); - ASSERT_TRUE(*i.ModifyVariable("s") == 100); + ASSERT_TRUE(std::get(*i.ModifyVariable("s")) == 100); } TEST(Parser, VariableDeclarationAdditionOfLiterals) @@ -49,7 +49,7 @@ TEST(Parser, VariableDeclarationAdditionOfLiterals) ASTInterpreter i; i.Run(expr.get()); ASSERT_TRUE(i.HasVariable("s")); - ASSERT_DOUBLE_EQ(*i.ModifyVariable("s"), 11.0); + ASSERT_DOUBLE_EQ(std::get(*i.ModifyVariable("s")), 11.0); } TEST(Parser, VariableDeclarationAdditionOfVariables) @@ -62,9 +62,9 @@ TEST(Parser, VariableDeclarationAdditionOfVariables) ASSERT_TRUE(i.HasVariable("a")); ASSERT_TRUE(i.HasVariable("b")); ASSERT_TRUE(i.HasVariable("c")); - ASSERT_DOUBLE_EQ(*i.ModifyVariable("a"), 5.0); - ASSERT_DOUBLE_EQ(*i.ModifyVariable("b"), 4.0); - ASSERT_DOUBLE_EQ(*i.ModifyVariable("c"), 9.0); + ASSERT_DOUBLE_EQ(std::get(*i.ModifyVariable("a")), 5.0); + ASSERT_DOUBLE_EQ(std::get(*i.ModifyVariable("b")), 4.0); + ASSERT_DOUBLE_EQ(std::get(*i.ModifyVariable("c")), 9.0); } TEST(Parser, VariableDeclarationMultiplicationOfLiterals) @@ -75,7 +75,7 @@ TEST(Parser, VariableDeclarationMultiplicationOfLiterals) ASTInterpreter i; i.Run(expr.get()); ASSERT_TRUE(i.HasVariable("s")); - ASSERT_DOUBLE_EQ(*i.ModifyVariable("s"), 30.0); + ASSERT_DOUBLE_EQ(std::get(*i.ModifyVariable("s")), 30.0); } TEST(Parser, VariableDeclarationMultiplicationOfVariables) @@ -88,9 +88,9 @@ TEST(Parser, VariableDeclarationMultiplicationOfVariables) ASSERT_TRUE(i.HasVariable("a")); ASSERT_TRUE(i.HasVariable("b")); ASSERT_TRUE(i.HasVariable("c")); - ASSERT_DOUBLE_EQ(*i.ModifyVariable("a"), 5.0); - ASSERT_DOUBLE_EQ(*i.ModifyVariable("b"), 4.0); - ASSERT_DOUBLE_EQ(*i.ModifyVariable("c"), 20.0); + ASSERT_DOUBLE_EQ(std::get(*i.ModifyVariable("a")), 5.0); + ASSERT_DOUBLE_EQ(std::get(*i.ModifyVariable("b")), 4.0); + ASSERT_DOUBLE_EQ(std::get(*i.ModifyVariable("c")), 20.0); } @@ -103,10 +103,10 @@ TEST(Parser, Unary) i.Run(expr.get()); ASSERT_TRUE(i.HasVariable("a")); ASSERT_TRUE(i.HasVariable("b")); - ASSERT_DOUBLE_EQ(*i.ModifyVariable("a"), 6.0); - ASSERT_DOUBLE_EQ(*i.ModifyVariable("b"), 5.0); - ASSERT_DOUBLE_EQ(*i.ModifyVariable("minusB"), -5.0); - ASSERT_DOUBLE_EQ(*i.ModifyVariable("plusB"), +5.0); + ASSERT_DOUBLE_EQ(std::get(*i.ModifyVariable("a")), 6.0); + ASSERT_DOUBLE_EQ(std::get(*i.ModifyVariable("b")), 5.0); + ASSERT_DOUBLE_EQ(std::get(*i.ModifyVariable("minusB")), -5.0); + ASSERT_DOUBLE_EQ(std::get(*i.ModifyVariable("plusB")), +5.0); } @@ -120,8 +120,8 @@ TEST(Parser, If) i.Run(expr.get()); ASSERT_TRUE(i.HasVariable("a")); ASSERT_TRUE(i.HasVariable("b")); - ASSERT_DOUBLE_EQ(*i.ModifyVariable("a"), 6.0); - ASSERT_DOUBLE_EQ(*i.ModifyVariable("b"), 5.0); + ASSERT_DOUBLE_EQ(std::get(*i.ModifyVariable("a")), 6.0); + ASSERT_DOUBLE_EQ(std::get(*i.ModifyVariable("b")), 5.0); } { IPLVector tokens = Tokenize("var a = 5; var b = 3; if(a == 5)a++; b++; b++;").tokens; @@ -131,8 +131,8 @@ TEST(Parser, If) i.Run(expr.get()); ASSERT_TRUE(i.HasVariable("a")); ASSERT_TRUE(i.HasVariable("b")); - ASSERT_DOUBLE_EQ(*i.ModifyVariable("a"), 6.0); - ASSERT_DOUBLE_EQ(*i.ModifyVariable("b"), 5.0); + ASSERT_DOUBLE_EQ(std::get(*i.ModifyVariable("a")), 6.0); + ASSERT_DOUBLE_EQ(std::get(*i.ModifyVariable("b")), 5.0); } { @@ -143,8 +143,8 @@ TEST(Parser, If) i.Run(expr.get()); ASSERT_TRUE(i.HasVariable("a")); ASSERT_TRUE(i.HasVariable("b")); - ASSERT_DOUBLE_EQ(*i.ModifyVariable("a"), 5.0); - ASSERT_DOUBLE_EQ(*i.ModifyVariable("b"), 5.0); + ASSERT_DOUBLE_EQ(std::get(*i.ModifyVariable("a")), 5.0); + ASSERT_DOUBLE_EQ(std::get(*i.ModifyVariable("b")), 5.0); } { @@ -155,8 +155,8 @@ TEST(Parser, If) i.Run(expr.get()); ASSERT_TRUE(i.HasVariable("a")); ASSERT_TRUE(i.HasVariable("b")); - ASSERT_DOUBLE_EQ(*i.ModifyVariable("a"), 5.0); - ASSERT_DOUBLE_EQ(*i.ModifyVariable("b"), 5.0); + ASSERT_DOUBLE_EQ(std::get(*i.ModifyVariable("a")), 5.0); + ASSERT_DOUBLE_EQ(std::get(*i.ModifyVariable("b")), 5.0); } { @@ -167,8 +167,8 @@ TEST(Parser, If) i.Run(expr.get()); ASSERT_TRUE(i.HasVariable("a")); ASSERT_TRUE(i.HasVariable("b")); - ASSERT_DOUBLE_EQ(*i.ModifyVariable("a"), 6.0); - ASSERT_DOUBLE_EQ(*i.ModifyVariable("b"), 4.0); + ASSERT_DOUBLE_EQ(std::get(*i.ModifyVariable("a")), 6.0); + ASSERT_DOUBLE_EQ(std::get(*i.ModifyVariable("b")), 4.0); } } @@ -181,7 +181,7 @@ TEST(Parser, For) ASTInterpreter i; i.Run(expr.get()); ASSERT_TRUE(i.HasVariable("i")); - ASSERT_DOUBLE_EQ(*i.ModifyVariable("i"), 45.0); + ASSERT_DOUBLE_EQ(std::get(*i.ModifyVariable("i")), 45.0); } { IPLVector tokens = Tokenize("var i = 0; for (var j = 0; j < 10; j++) i = i + j;").tokens; @@ -189,7 +189,7 @@ TEST(Parser, For) ASTInterpreter i; i.Run(expr.get()); ASSERT_TRUE(i.HasVariable("i")); - ASSERT_DOUBLE_EQ(*i.ModifyVariable("i"), 45.0); + ASSERT_DOUBLE_EQ(std::get(*i.ModifyVariable("i")), 45.0); } } -- cgit v1.3.1-23-gd82d From 0d0159f70b0f3b23d6a4187d43167ded6b104e0f Mon Sep 17 00:00:00 2001 From: Dimitar Trendafilov Date: Mon, 2 Nov 2020 09:03:05 +0200 Subject: Support for strings in the AST interpreter --- JSImpl/src/ASTInterpreter.cpp | 114 ++++++++++++++++++++++++++++++++++++------ JSImpl/src/ASTInterpreter.h | 3 +- JSImpl/src/main.cpp | 6 ++- 3 files changed, 105 insertions(+), 18 deletions(-) (limited to 'JSImpl/src/ASTInterpreter.cpp') diff --git a/JSImpl/src/ASTInterpreter.cpp b/JSImpl/src/ASTInterpreter.cpp index fd631ca..9503494 100644 --- a/JSImpl/src/ASTInterpreter.cpp +++ b/JSImpl/src/ASTInterpreter.cpp @@ -26,95 +26,166 @@ namespace { return d != 0.0; } + bool operator()(const IPLString&) const + { + return true; + } }; - struct ValueAdd + struct UnsupportedOpReport { + template + ASTInterpreter::ValuePtr operator()(V) const + { + throw std::runtime_error("unsupported operation"); + } + + template + ASTInterpreter::ValuePtr operator()(L, R) const + { + throw std::runtime_error("unsupported operation"); + } + }; + + struct ValueAdd : UnsupportedOpReport + { + using UnsupportedOpReport::operator(); + ASTInterpreter::ValuePtr operator()(double l, double r) const { return MakeValue(l + r); } + + ASTInterpreter::ValuePtr operator()(const IPLString& l, const IPLString& r) const + { + return MakeValue(l + r); + } }; - struct ValueMinus + struct ValueMinus : UnsupportedOpReport { + using UnsupportedOpReport::operator(); + ASTInterpreter::ValuePtr operator()(double l, double r) const { return MakeValue(l - r); } }; - struct ValueProduct + + struct ValueProduct : UnsupportedOpReport { + using UnsupportedOpReport::operator(); + ASTInterpreter::ValuePtr operator()(double l, double r) const { return MakeValue(l * r); } }; - struct ValueDivide + + struct ValueDivide : UnsupportedOpReport { + using UnsupportedOpReport::operator(); + ASTInterpreter::ValuePtr operator()(double l, double r) const { return MakeValue(l / r); } }; - struct ValueLess + + struct ValueLess : UnsupportedOpReport { - ASTInterpreter::ValuePtr operator()(double l, double r) const + using UnsupportedOpReport::operator(); + + template + ASTInterpreter::ValuePtr operator()(const V& l, const V& r) const { return MakeValue(l < r); } }; - struct ValueLessEqual + struct ValueLessEqual : UnsupportedOpReport { - ASTInterpreter::ValuePtr operator()(double l, double r) const + using UnsupportedOpReport::operator(); + + template + ASTInterpreter::ValuePtr operator()(V l, V r) const { return MakeValue(l <= r); } }; - struct ValueGreater + + struct ValueGreater : UnsupportedOpReport { - ASTInterpreter::ValuePtr operator()(double l, double r) const + using UnsupportedOpReport::operator(); + + template + ASTInterpreter::ValuePtr operator()(V l, V r) const { return MakeValue(l > r); } }; - struct ValueGreaterEqual + + struct ValueGreaterEqual : UnsupportedOpReport { - ASTInterpreter::ValuePtr operator()(double l, double r) const + using UnsupportedOpReport::operator(); + + template + ASTInterpreter::ValuePtr operator()(V l, V r) const { return MakeValue(l >= r); } }; - struct ValueEqualEqual + struct ValueEqualEqual : UnsupportedOpReport { + using UnsupportedOpReport::operator(); + ASTInterpreter::ValuePtr operator()(double left, double right) const { return MakeValue(fabs(left - right) <= 0.0001); } + + ASTInterpreter::ValuePtr operator()(const IPLString& left, const IPLString& right) const + { + return MakeValue(left == right); + } }; - struct ValueBangEqual + struct ValueBangEqual : UnsupportedOpReport { + using UnsupportedOpReport::operator(); + ASTInterpreter::ValuePtr operator()(double left, double right) const { return MakeValue(fabs(left - right) > 0.0001); } + ASTInterpreter::ValuePtr operator()(const IPLString& left, const IPLString& right) const + { + return MakeValue(left != right); + } }; - struct ValueUnaryMinus + struct ValueUnaryMinus : UnsupportedOpReport { + using UnsupportedOpReport::operator(); + ASTInterpreter::ValuePtr operator()(double v) const { return MakeValue(-v); } }; + struct ValueIncrement { void operator()(double& v) const { v += 1; } + + template + void operator()(V&) const + { + throw std::runtime_error("unsupported operation"); + } }; struct ValueDecrement @@ -123,6 +194,12 @@ namespace { v -= 1; } + + template + void operator()(V&) const + { + throw std::runtime_error("unsupported operation"); + } }; struct ValuePrint @@ -137,6 +214,11 @@ namespace Printer->PrintVariable(Name, value); } + void operator()(const IPLString& value) const + { + Printer->PrintVariable(Name, value); + } + const char* Name; ASTInterpreter::Printer* Printer; }; @@ -281,7 +363,7 @@ void ASTInterpreter::Visit(LiteralUndefined* e) { NOT_IMPLEMENTED; } void ASTInterpreter::Visit(LiteralString* e) { - NOT_IMPLEMENTED; + m_Evaluation.push_back(MakeValue(e->GetValue())); } void ASTInterpreter::Visit(LiteralObject* e) diff --git a/JSImpl/src/ASTInterpreter.h b/JSImpl/src/ASTInterpreter.h index ba797c1..cce6108 100644 --- a/JSImpl/src/ASTInterpreter.h +++ b/JSImpl/src/ASTInterpreter.h @@ -11,7 +11,7 @@ public: ~ASTInterpreter(); - typedef std::variant Value; + typedef std::variant Value; typedef IPLSharedPtr ValuePtr; typedef IPLVector ValueStack; @@ -47,6 +47,7 @@ public: { public: virtual void PrintVariable(const char* name, double value) = 0; + virtual void PrintVariable(const char* name, const IPLString& value) = 0; }; void Print(Printer& p); diff --git a/JSImpl/src/main.cpp b/JSImpl/src/main.cpp index 6ed1122..06421a7 100644 --- a/JSImpl/src/main.cpp +++ b/JSImpl/src/main.cpp @@ -38,7 +38,11 @@ class InterpreterPrinter : public ASTInterpreter::Printer public: virtual void PrintVariable(const char* name, double value) override { - std::cout << name << ": " << value << std::endl; + std::cout << name << ": number : " << value << std::endl; + } + virtual void PrintVariable(const char* name, const IPLString& value) override + { + std::cout << name << ": string : " << value << std::endl; } }; -- cgit v1.3.1-23-gd82d From f4598a0e6deb5fb1a63b4fc125804aa85ca818bd Mon Sep 17 00:00:00 2001 From: Dimitar Trendafilov Date: Mon, 9 Nov 2020 22:08:58 +0200 Subject: Evaluate empty strings as false --- JSImpl/src/ASTInterpreter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'JSImpl/src/ASTInterpreter.cpp') diff --git a/JSImpl/src/ASTInterpreter.cpp b/JSImpl/src/ASTInterpreter.cpp index 9503494..f550da9 100644 --- a/JSImpl/src/ASTInterpreter.cpp +++ b/JSImpl/src/ASTInterpreter.cpp @@ -26,9 +26,9 @@ namespace { return d != 0.0; } - bool operator()(const IPLString&) const + bool operator()(const IPLString& s) const { - return true; + return !s.empty(); } }; -- cgit v1.3.1-23-gd82d