11 #include "utils/logger.hpp"
20 static inline bool is_number(
const std::shared_ptr<ast::Expression>&
node) {
28 return std::dynamic_pointer_cast<ast::Integer>(
node)->eval();
30 return std::dynamic_pointer_cast<ast::Float>(
node)->to_double();
32 return std::dynamic_pointer_cast<ast::Double>(
node)->to_double();
34 throw std::runtime_error(
"Invalid type passed to is_number()");
60 throw std::logic_error(
"Invalid binary operator in constant folding");
79 node.visit_children(*
this);
80 auto expr =
node.get_expression();
81 if (expr->is_wrapped_expression()) {
82 auto e = std::dynamic_pointer_cast<ast::WrappedExpression>(expr);
83 node.set_expression(e->get_expression());
108 node.visit_children(*
this);
109 node.visit_children(*
this);
112 auto expr =
node.get_expression();
115 bool is_parentheses =
false;
120 if (expr->is_paren_expression()) {
121 auto e = std::dynamic_pointer_cast<ast::ParenExpression>(expr);
122 expr = e->get_expression();
123 is_parentheses =
true;
127 if (!expr->is_binary_expression()) {
130 if (is_parentheses) {
136 auto binary_expr = std::dynamic_pointer_cast<ast::BinaryExpression>(expr);
137 auto lhs = binary_expr->get_lhs();
138 auto rhs = binary_expr->get_rhs();
139 auto op = binary_expr->get_op().get_value();
147 if (lhs->is_wrapped_expression()) {
148 auto e = std::dynamic_pointer_cast<ast::WrappedExpression>(lhs);
149 lhs = e->get_expression();
152 if (
rhs->is_wrapped_expression()) {
153 auto e = std::dynamic_pointer_cast<ast::WrappedExpression>(
rhs);
154 rhs = e->get_expression();
162 const std::string& nmodl_before =
to_nmodl(binary_expr);
168 if (lhs->is_integer() &&
rhs->is_integer()) {
169 node.set_expression(std::make_shared<ast::Integer>(
static_cast<int>(
value),
nullptr));
170 }
else if (lhs->is_double() ||
rhs->is_double()) {
176 const std::string& nmodl_after =
to_nmodl(
node.get_expression());
177 logger->debug(
"ConstantFolderVisitor : expression {} folded to {}", nmodl_before, nmodl_after);
Auto generated AST classes declaration.
Wrap any other expression type.
void visit_wrapped_expression(ast::WrappedExpression &node) override
Visit wrapped node type and perform constant folding.
void visit_paren_expression(ast::ParenExpression &node) override
Visit parenthesis expression and simplify it.
Perform constant folding of integer/float/double expressions.
virtual bool is_integer() const noexcept
Check if the ast node is an instance of ast::Integer.
virtual bool is_float() const noexcept
Check if the ast node is an instance of ast::Float.
virtual bool is_double() const noexcept
Check if the ast node is an instance of ast::Double.
BinaryOp
enum Type for binary operators in NMODL
std::string to_string(double value, const std::string &format_spec)
Convert double value to string without trailing zeros.
void move(Item *q1, Item *q2, Item *q3)
static bool is_number(const std::shared_ptr< ast::Expression > &node)
check if given expression is a number note that the DEFINE node is already expanded to integer
static double compute(double lhs, ast::BinaryOp op, double rhs)
Evaluate binary operation TODO : add support for other binary operators like ^ (pow)
static bool supported_operator(ast::BinaryOp op)
operators that currently implemented
static double get_value(const std::shared_ptr< ast::Expression > &node)
get value of a number node TODO : eval method can be added to virtual base class
encapsulates code generation backend implementations
std::string to_nmodl(const ast::Ast &node, const std::set< ast::AstNodeType > &exclude_types)
Given AST node, return the NMODL string representation.
static Node * node(Object *)
Utility functions for visitors implementation.