diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 7886618ee..0e3a0b493 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -69,6 +69,12 @@ Expression*ExpAttribute::clone() const return new ExpAttribute(static_cast(base_->clone()), name_); } +void ExpAttribute::visit(ExprVisitor& func) +{ + base_->visit(func); + func(this); +} + ExpBinary::ExpBinary(Expression*op1, Expression*op2) : operand1_(op1), operand2_(op2) { @@ -90,6 +96,13 @@ bool ExpBinary::eval_operand2(ScopeBase*scope, int64_t&val) const return operand2_->evaluate(scope, val); } +void ExpBinary::visit(ExprVisitor& func) +{ + operand1_->visit(func); + operand2_->visit(func); + func(this); +} + ExpUnary::ExpUnary(Expression*op1) : operand1_(op1) { @@ -100,6 +113,12 @@ ExpUnary::~ExpUnary() delete operand1_; } +void ExpUnary::visit(ExprVisitor& func) +{ + operand1_->visit(func); + func(this); +} + ExpAggregate::ExpAggregate(std::list*el) : elements_(el? el->size() : 0) { @@ -135,6 +154,24 @@ Expression* ExpAggregate::clone() const return new ExpAggregate(new_elements); } +void ExpAggregate::visit(ExprVisitor& func) +{ + for(std::vector::iterator it = elements_.begin(); + it != elements_.end(); ++it) { + (*it)->extract_expression()->visit(func); + } + + for(std::vector::iterator it = aggregate_.begin(); + it != aggregate_.end(); ++it) { + if(Expression*choice_expr = it->choice->simple_expression(false)) + choice_expr->visit(func); + + it->expr->visit(func); + } + + func(this); +} + ExpAggregate::choice_t::choice_t(Expression*exp) : expr_(exp) { @@ -256,6 +293,13 @@ ExpConcat::~ExpConcat() delete operand2_; } +void ExpConcat::visit(ExprVisitor& func) +{ + operand1_->visit(func); + operand2_->visit(func); + func(this); +} + ExpConditional::ExpConditional(Expression*co, list*tru, list*fal) : cond_(co) @@ -304,6 +348,30 @@ Expression*ExpConditional::clone() const return new ExpConditional(cond_->clone(), new_true_clause, new_else_clause); } +void ExpConditional::visit(ExprVisitor& func) +{ + if(!true_clause_.empty()) { + for(std::list::iterator it = true_clause_.begin(); + it != true_clause_.end(); ++it) { + (*it)->visit(func); + } + } + + if(!else_clause_.empty()) { + for(std::list::iterator it = else_clause_.begin(); + it != else_clause_.end(); ++it) { + std::list& else_clause = (*it)->extract_true_clause(); + + for(std::list::iterator jt = else_clause.begin(); + jt != else_clause.end(); ++jt) { + (*jt)->visit(func); + } + } + } + + func(this); +} + ExpConditional::else_t::else_t(Expression*cond, std::list*tru) : cond_(cond) { @@ -378,6 +446,16 @@ Expression*ExpFunc::clone() const { return f; } +void ExpFunc::visit(ExprVisitor& func) { + if(!argv_.empty()) { + for(std::vector::iterator it = argv_.begin(); + it != argv_.end(); ++it) + (*it)->visit(func); + } + + func(this); +} + const VType* ExpFunc::func_ret_type() const { return def_ ? def_->peek_return_type() : NULL; @@ -481,6 +559,20 @@ void ExpName::set_range(Expression*msb, Expression*lsb) lsb_ = lsb; } +void ExpName::visit(ExprVisitor& func) +{ + if(prefix_.get()) + prefix_.get()->visit(func); + + if(index_) + index_->visit(func); + + if(lsb_) + lsb_->visit(func); + + func(this); +} + int ExpName::index_t::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; @@ -555,6 +647,12 @@ ExpCast::~ExpCast() { } +void ExpCast::visit(ExprVisitor& func) +{ + base_->visit(func); + func(this); +} + ExpNew::ExpNew(Expression*size) : size_(size) { @@ -565,6 +663,12 @@ ExpNew::~ExpNew() delete size_; } +void ExpNew::visit(ExprVisitor& func) +{ + size_->visit(func); + func(this); +} + ExpTime::ExpTime(uint64_t amount, timeunit_t unit) : amount_(amount), unit_(unit) { diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 717b1e116..479d207d5 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -38,6 +38,11 @@ class VTypeArray; class VTypePrimitive; class ExpName; +struct ExprVisitor { + virtual ~ExprVisitor() {}; + virtual void operator() (Expression*s) = 0; +}; + /* * The Expression class represents parsed expressions from the parsed * VHDL input. The Expression class is a virtual class that holds more @@ -120,6 +125,9 @@ class Expression : public LineInfo { virtual void dump(ostream&out, int indent = 0) const =0; virtual ostream& dump_inline(ostream&out) const; + // Recursively visits a tree of expressions (useful of complex expressions). + virtual void visit(ExprVisitor& func) { func(this); } + protected: // This function is called by the derived class during // elaboration to set the type of the current expression that @@ -160,6 +168,7 @@ class ExpUnary : public Expression { inline const Expression*peek_operand() const { return operand1_; } const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const; + void visit(ExprVisitor& func); protected: inline void write_to_stream_operand1(std::ostream&fd) const @@ -186,6 +195,7 @@ class ExpBinary : public Expression { inline const Expression* peek_operand2(void) const { return operand2_; } const VType*probe_type(Entity*ent, ScopeBase*scope) const; + void visit(ExprVisitor& func); protected: @@ -299,6 +309,7 @@ class ExpAggregate : public Expression { void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; + void visit(ExprVisitor& func); private: int elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArray*ltype); @@ -360,6 +371,7 @@ class ExpAttribute : public Expression { bool evaluate(ScopeBase*scope, int64_t&val) const; bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const; void dump(ostream&out, int indent = 0) const; + void visit(ExprVisitor& func); private: ExpName*base_; @@ -430,6 +442,7 @@ class ExpConcat : public Expression { virtual bool evaluate(ScopeBase*scope, int64_t&val) const; bool is_primary(void) const; void dump(ostream&out, int indent = 0) const; + void visit(ExprVisitor& func); private: int elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArray*ltype); @@ -457,6 +470,7 @@ class ExpConditional : public Expression { int emit_when_else(ostream&out, Entity*ent, ScopeBase*scope); int emit_else(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; + std::list& extract_true_clause() { return true_clause_; } private: Expression*cond_; @@ -475,6 +489,7 @@ class ExpConditional : public Expression { void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; + void visit(ExprVisitor& func); private: Expression*cond_; @@ -528,6 +543,7 @@ class ExpFunc : public Expression { void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; + void visit(ExprVisitor& func); // NOTE: does not handle expressions in subprogram private: perm_string name_; @@ -638,8 +654,8 @@ class ExpName : public Expression { void dump(ostream&out, int indent = 0) const; inline const char* name() const { return name_; } inline const perm_string& peek_name() const { return name_; } - void set_range(Expression*msb, Expression*lsb); + void visit(ExprVisitor& func); private: class index_t { @@ -811,6 +827,7 @@ class ExpCast : public Expression { void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; + void visit(ExprVisitor& func); private: Expression*base_; @@ -833,6 +850,7 @@ class ExpNew : public Expression { void write_to_stream(std::ostream&) const {}; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; + void visit(ExprVisitor& func); private: Expression*size_;