Website Summary Files Commits Branches @commit @diff @stats
path: root / JSImpl
diff options
context:
space:
mode:
Commitd8704c516b3a8b32817ffcad1868d7cd135efe48 (patch)
Author
 Dimitar Trendafilov <trendafilov.dn@gmail.com>
2020-11-01 21:34:40 +0200
Committer
 Dimitar Trendafilov <dimitar@coherent-labs.com>
2020-11-09 22:08:19 +0200
Files9aa5a380b09ef52e899a54ac90d347a917b904ee /JSImpl
IPL-d8704c516b3a8b32817ffcad1868d7cd135efe48.tar
IPL-d8704c516b3a8b32817ffcad1868d7cd135efe48.tar.gz
IPL-d8704c516b3a8b32817ffcad1868d7cd135efe48.zip
Parentb93662dbcc9d30c69cce7d1342606cafc60bb3f0 (diff)
Move AST interpreter value to std::variant
4 files changed, 174 insertions, 44 deletions
-rw-r--r--JSImpl/solution/genie.lua2
-rw-r--r--JSImpl/src/ASTInterpreter.cpp161
-rw-r--r--JSImpl/src/ASTInterpreter.h3
-rw-r--r--JSImpl/test/ParserTests.cpp52
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 <typename T>
ASTInterpreter::ValuePtr MakeValue(T&& v)
{
- return IPLMakeSharePtr<double>(v);
+ return IPLMakeSharePtr<ASTInterpreter::Value>(v);
}
template <typename T>
ASTInterpreter::ValuePtr MakeValue(const T& v)
{
- return IPLMakeSharePtr<double>(v);
+ return IPLMakeSharePtr<ASTInterpreter::Value>(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<double> ValuePtr;
+ typedef std::variant<double> Value;
+ typedef IPLSharedPtr<Value> ValuePtr;
typedef IPLVector<ValuePtr> 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<double>(*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<double>(*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<double>(*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<double>(*i.ModifyVariable("a")), 5.0);
+ ASSERT_DOUBLE_EQ(std::get<double>(*i.ModifyVariable("b")), 4.0);
+ ASSERT_DOUBLE_EQ(std::get<double>(*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<double>(*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<double>(*i.ModifyVariable("a")), 5.0);
+ ASSERT_DOUBLE_EQ(std::get<double>(*i.ModifyVariable("b")), 4.0);
+ ASSERT_DOUBLE_EQ(std::get<double>(*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<double>(*i.ModifyVariable("a")), 6.0);
+ ASSERT_DOUBLE_EQ(std::get<double>(*i.ModifyVariable("b")), 5.0);
+ ASSERT_DOUBLE_EQ(std::get<double>(*i.ModifyVariable("minusB")), -5.0);
+ ASSERT_DOUBLE_EQ(std::get<double>(*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<double>(*i.ModifyVariable("a")), 6.0);
+ ASSERT_DOUBLE_EQ(std::get<double>(*i.ModifyVariable("b")), 5.0);
}
{
IPLVector<Token> 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<double>(*i.ModifyVariable("a")), 6.0);
+ ASSERT_DOUBLE_EQ(std::get<double>(*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<double>(*i.ModifyVariable("a")), 5.0);
+ ASSERT_DOUBLE_EQ(std::get<double>(*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<double>(*i.ModifyVariable("a")), 5.0);
+ ASSERT_DOUBLE_EQ(std::get<double>(*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<double>(*i.ModifyVariable("a")), 6.0);
+ ASSERT_DOUBLE_EQ(std::get<double>(*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<double>(*i.ModifyVariable("i")), 45.0);
}
{
IPLVector<Token> 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<double>(*i.ModifyVariable("i")), 45.0);
}
}