vhdlpp: Clone routines for Expression & VType classes.

This commit is contained in:
Maciej Suminski 2015-02-02 11:00:59 +01:00
parent 60077f4f06
commit 8a854affa6
5 changed files with 211 additions and 9 deletions

View File

@ -64,6 +64,11 @@ ExpAttribute::~ExpAttribute()
delete base_;
}
Expression*ExpAttribute::clone() const
{
return new ExpAttribute(static_cast<ExpName*>(base_->clone()), name_);
}
ExpBinary::ExpBinary(Expression*op1, Expression*op2)
: operand1_(op1), operand2_(op2)
{
@ -113,6 +118,23 @@ ExpAggregate::~ExpAggregate()
delete elements_[idx];
}
Expression* ExpAggregate::clone() const
{
std::list<element_t*>*new_elements = NULL;
if(!elements_.empty()) {
new_elements = new std::list<element_t*>();
for(std::vector<element_t*>::const_iterator it = elements_.begin();
it != elements_.end(); ++it) {
new_elements->push_back(new element_t(**it));
}
}
assert(aggregate_.empty()); // cloning should not happen after elab
return new ExpAggregate(new_elements);
}
ExpAggregate::choice_t::choice_t(Expression*exp)
: expr_(exp)
{
@ -127,6 +149,15 @@ ExpAggregate::choice_t::choice_t(prange_t*rang)
{
}
ExpAggregate::choice_t::choice_t(const choice_t&other)
{
if(Expression*e = other.expr_.get())
expr_.reset(e->clone());
if(other.range_.get())
range_.reset(new prange_t(*other.range_.get()));
}
ExpAggregate::choice_t::~choice_t()
{
}
@ -160,6 +191,18 @@ ExpAggregate::element_t::element_t(list<choice_t*>*fields, Expression*val)
}
}
ExpAggregate::element_t::element_t(const ExpAggregate::element_t&other)
{
fields_.reserve(other.fields_.size());
for(std::vector<choice_t*>::const_iterator it = other.fields_.begin();
it != other.fields_.end(); ++it) {
fields_.push_back(*it);
}
val_ = other.val_->clone();
}
ExpAggregate::element_t::~element_t()
{
for (size_t idx = 0 ; idx < fields_.size() ; idx += 1)
@ -236,12 +279,46 @@ ExpConditional::~ExpConditional()
}
}
Expression*ExpConditional::clone() const
{
std::list<Expression*>*new_true_clause = NULL;
if(!true_clause_.empty()) {
new_true_clause = new std::list<Expression*>();
for(std::list<Expression*>::const_iterator it = true_clause_.begin();
it != true_clause_.end(); ++it) {
new_true_clause->push_back((*it)->clone());
}
}
std::list<else_t*>*new_else_clause = NULL;
if(!else_clause_.empty()) {
new_else_clause = new std::list<else_t*>();
for(std::list<else_t*>::const_iterator it = else_clause_.begin();
it != else_clause_.end(); ++it) {
new_else_clause->push_back(new else_t(**it));
}
}
return new ExpConditional(cond_->clone(), new_true_clause, new_else_clause);
}
ExpConditional::else_t::else_t(Expression*cond, std::list<Expression*>*tru)
: cond_(cond)
{
if (tru) true_clause_.splice(true_clause_.end(), *tru);
}
ExpConditional::else_t::else_t(const else_t&other)
{
cond_ = other.cond_->clone();
for(std::list<Expression*>::const_iterator it = other.true_clause_.begin();
it != other.true_clause_.end(); ++it) {
true_clause_.push_back((*it)->clone());
}
}
ExpConditional::else_t::~else_t()
{
delete cond_;
@ -284,6 +361,22 @@ ExpFunc::~ExpFunc()
delete argv_[idx];
}
Expression*ExpFunc::clone() const {
std::list<Expression*>*new_args = NULL;
if(!argv_.empty()) {
new_args = new std::list<Expression*>();
for(std::vector<Expression*>::const_iterator it = argv_.begin();
it != argv_.end(); ++it)
new_args->push_back((*it)->clone());
}
ExpFunc*f = new ExpFunc(name_, new_args);
f->def_ = def_;
return f;
}
const VType* ExpFunc::func_ret_type() const
{
return def_ ? def_->peek_return_type() : NULL;

View File

@ -36,7 +36,6 @@ class Subprogram;
class VType;
class VTypeArray;
class VTypePrimitive;
class ExpName;
/*
@ -50,6 +49,9 @@ class Expression : public LineInfo {
Expression();
virtual ~Expression() =0;
// Returns a deep copy of the expression.
virtual Expression*clone() const =0;
// This virtual method handles the special case of elaborating
// an expression that is the l-value of a sequential variable
// assignment. This generates an error for most cases, but
@ -133,6 +135,13 @@ class Expression : public LineInfo {
Expression& operator = (const Expression&);
};
/*
* Checks before cloning if the other expression actually exists (!=NULL).
*/
static inline Expression*safe_clone(const Expression*other) {
return (other ? other->clone() : NULL);
}
static inline void FILE_NAME(Expression*tgt, const LineInfo*src)
{
tgt->set_line(*src);
@ -149,6 +158,8 @@ class ExpUnary : public Expression {
ExpUnary(Expression*op1);
virtual ~ExpUnary() =0;
inline const Expression*peek_operand() const { return operand1_; }
const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
protected:
@ -172,8 +183,8 @@ class ExpBinary : public Expression {
ExpBinary(Expression*op1, Expression*op2);
virtual ~ExpBinary() =0;
const Expression* peek_operand1(void) const { return operand1_; }
const Expression* peek_operand2(void) const { return operand2_; }
inline const Expression* peek_operand1(void) const { return operand1_; }
inline const Expression* peek_operand2(void) const { return operand2_; }
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
@ -218,6 +229,9 @@ class ExpAggregate : public Expression {
explicit choice_t(perm_string name);
// discreate_range choice
explicit choice_t(prange_t*ran);
choice_t(const choice_t&other);
~choice_t();
// true if this represents an "others" choice
@ -234,11 +248,17 @@ class ExpAggregate : public Expression {
std::auto_ptr<Expression>expr_;
std::auto_ptr<prange_t> range_;
private: // not implemented
choice_t(const choice_t&);
choice_t& operator= (const choice_t&);
};
struct choice_element {
choice_element() : choice(), expr() {}
choice_element(const choice_element&other) {
choice = other.choice ? new choice_t(*other.choice) : NULL;
expr = safe_clone(other.expr);
}
choice_t*choice;
Expression*expr;
bool alias_flag;
@ -250,6 +270,7 @@ class ExpAggregate : public Expression {
class element_t {
public:
explicit element_t(std::list<choice_t*>*fields, Expression*val);
element_t(const element_t&other);
~element_t();
size_t count_choices() const { return fields_.size(); }
@ -264,7 +285,6 @@ class ExpAggregate : public Expression {
std::vector<choice_t*>fields_;
Expression*val_;
private: // not implemented
element_t(const element_t&);
element_t& operator = (const element_t&);
};
@ -272,6 +292,7 @@ class ExpAggregate : public Expression {
ExpAggregate(std::list<element_t*>*el);
~ExpAggregate();
Expression*clone() const;
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
@ -304,6 +325,10 @@ class ExpArithmetic : public ExpBinary {
ExpArithmetic(ExpArithmetic::fun_t op, Expression*op1, Expression*op2);
~ExpArithmetic();
Expression*clone() const {
return new ExpArithmetic(fun_, peek_operand1()->clone(), peek_operand2()->clone());
}
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd);
int emit(ostream&out, Entity*ent, ScopeBase*scope);
@ -323,6 +348,8 @@ class ExpAttribute : public Expression {
ExpAttribute(ExpName*base, perm_string name);
~ExpAttribute();
Expression*clone() const;
inline perm_string peek_attribute() const { return name_; }
inline const ExpName* peek_base() const { return base_; }
@ -344,8 +371,11 @@ class ExpBitstring : public Expression {
public:
explicit ExpBitstring(const char*);
ExpBitstring(const ExpBitstring&other) : Expression() { value_ = other.value_; }
~ExpBitstring();
Expression*clone() const { return new ExpBitstring(*this); }
const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd);
@ -361,8 +391,11 @@ class ExpCharacter : public Expression {
public:
ExpCharacter(char val);
ExpCharacter(const ExpCharacter&other) : Expression() { value_ = other.value_; }
~ExpCharacter();
Expression*clone() const { return new ExpCharacter(*this); }
const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd);
@ -386,6 +419,10 @@ class ExpConcat : public Expression {
ExpConcat(Expression*op1, Expression*op2);
~ExpConcat();
Expression*clone() const {
return new ExpConcat(operand1_->clone(), operand2_->clone());
}
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
@ -414,6 +451,7 @@ class ExpConditional : public Expression {
class else_t : public LineInfo {
public:
else_t(Expression*cond, std::list<Expression*>*tru);
else_t(const else_t&other);
~else_t();
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*lt);
@ -431,6 +469,8 @@ class ExpConditional : public Expression {
std::list<else_t*>*fal);
~ExpConditional();
Expression*clone() const;
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd);
@ -456,6 +496,8 @@ class ExpEdge : public ExpUnary {
explicit ExpEdge(ExpEdge::fun_t ty, Expression*op);
~ExpEdge();
Expression*clone() const { return new ExpEdge(fun_, peek_operand()->clone()); }
inline fun_t edge_fun() const { return fun_; }
void write_to_stream(std::ostream&fd);
@ -473,6 +515,8 @@ class ExpFunc : public Expression {
ExpFunc(perm_string nn, std::list<Expression*>*args);
~ExpFunc();
Expression*clone() const;
inline perm_string func_name() const { return name_; }
inline size_t func_args() const { return argv_.size(); }
inline const Expression*func_arg(size_t idx) const { return argv_[idx]; }
@ -494,8 +538,11 @@ class ExpInteger : public Expression {
public:
ExpInteger(int64_t val);
ExpInteger(const ExpInteger&other) : Expression(), value_(other.value_) {}
~ExpInteger();
Expression*clone() const { return new ExpInteger(*this); }
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd);
@ -514,8 +561,11 @@ class ExpReal : public Expression {
public:
ExpReal(double val);
ExpReal(const ExpReal&other) : Expression(), value_(other.value_) {}
~ExpReal();
Expression*clone() const { return new ExpReal(*this); }
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd);
@ -538,6 +588,10 @@ class ExpLogical : public ExpBinary {
ExpLogical(ExpLogical::fun_t ty, Expression*op1, Expression*op2);
~ExpLogical();
Expression*clone() const {
return new ExpLogical(fun_, peek_operand1()->clone(), peek_operand2()->clone());
}
inline fun_t logic_fun() const { return fun_; }
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
@ -565,6 +619,10 @@ class ExpName : public Expression {
~ExpName();
public: // Base methods
Expression*clone() const {
return new ExpName(static_cast<ExpName*>(safe_clone(prefix_.get())),
name_, safe_clone(index_), safe_clone(lsb_));
}
int elaborate_lval(Entity*ent, ScopeBase*scope, bool);
int elaborate_rval(Entity*ent, ScopeBase*scope, const InterfacePort*);
const VType* probe_type(Entity*ent, ScopeBase*scope) const;
@ -578,7 +636,7 @@ class ExpName : public Expression {
bool symbolic_compare(const Expression*that) const;
void dump(ostream&out, int indent = 0) const;
const char* name() const;
inline perm_string peek_name() const { return name_; }
inline const perm_string& peek_name() const { return name_; }
void set_range(Expression*msb, Expression*lsb);
@ -620,6 +678,10 @@ class ExpRelation : public ExpBinary {
ExpRelation(ExpRelation::fun_t ty, Expression*op1, Expression*op2);
~ExpRelation();
Expression*clone() const {
return new ExpRelation(fun_, peek_operand1()->clone(), peek_operand2()->clone());
}
const VType* probe_type(Entity*ent, ScopeBase*scope) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd);
@ -634,8 +696,11 @@ class ExpString : public Expression {
public:
explicit ExpString(const char*);
ExpString(const ExpString&other) : Expression(), value_(other.value_) {}
~ExpString();
Expression*clone() const { return new ExpString(*this); }
const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd);
@ -657,6 +722,8 @@ class ExpUAbs : public ExpUnary {
ExpUAbs(Expression*op1);
~ExpUAbs();
Expression*clone() const { return new ExpUAbs(peek_operand()->clone()); }
void write_to_stream(std::ostream&fd);
int emit(ostream&out, Entity*ent, ScopeBase*scope);
void dump(ostream&out, int indent = 0) const;
@ -668,6 +735,8 @@ class ExpUNot : public ExpUnary {
ExpUNot(Expression*op1);
~ExpUNot();
Expression*clone() const { return new ExpUNot(peek_operand()->clone()); }
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd);
int emit(ostream&out, Entity*ent, ScopeBase*scope);
@ -683,6 +752,8 @@ class ExpCast : public Expression {
ExpCast(Expression*base, const VType*type);
~ExpCast();
Expression*clone() const { return new ExpCast(base_->clone(), type_->clone()); }
inline int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) {
return base_->elaborate_expr(ent, scope, type_);
}
@ -705,6 +776,8 @@ class ExpNew : public Expression {
ExpNew(Expression*size);
~ExpNew();
Expression*clone() const { return new ExpNew(size_->clone()); }
// There is no 'new' in VHDL - do not emit anything
void write_to_stream(std::ostream&) {};
int emit(ostream&out, Entity*ent, ScopeBase*scope);

View File

@ -72,6 +72,9 @@ class prange_t {
public:
prange_t(Expression* left, Expression* right, bool dir)
: left_(left), right_(right), direction_(dir), auto_dir_(false) {}
prange_t(const prange_t&other) :
left_(other.left_->clone()), right_(other.right_->clone()),
direction_(other.direction_), auto_dir_(other.auto_dir_) {}
~prange_t() { delete left_; delete right_; }
void dump(ostream&out, int indent) const;
@ -91,7 +94,6 @@ class prange_t {
bool auto_dir_;
private: //not implemented
prange_t(const prange_t&);
prange_t operator=(const prange_t&);
};

View File

@ -26,7 +26,6 @@
using namespace std;
VType::~VType()
{
}
@ -76,6 +75,11 @@ void VTypePrimitive::show(ostream&out) const
}
}
VTypeArray::range_t*VTypeArray::range_t::clone() const
{
return new VTypeArray::range_t(safe_clone(msb_), safe_clone(lsb_), direction_);
}
VTypeArray::VTypeArray(const VType*element, const vector<VTypeArray::range_t>&r, bool sv)
: etype_(element), ranges_(r), signed_flag_(sv), parent_(NULL)
{
@ -106,6 +110,18 @@ VTypeArray::~VTypeArray()
{
}
VType*VTypeArray::clone() const {
std::vector<range_t> new_ranges;
new_ranges.reserve(ranges_.size());
for(std::vector<range_t>::const_iterator it = ranges_.begin();
it != ranges_.end(); ++it) {
new_ranges.push_back(*(it->clone()));
}
VTypeArray*a = new VTypeArray(etype_->clone(), new_ranges, signed_flag_);
a->set_parent_type(parent_);
return a;
}
const VType* VTypeArray::basic_type(bool typedef_allowed) const
{
const VType*t = etype_;

View File

@ -51,6 +51,8 @@ class VType {
VType() { }
virtual ~VType() =0;
virtual VType*clone() const =0;
// This is rarely used, but some types may have expressions
// that need to be elaborated.
virtual int elaborate(Entity*end, ScopeBase*scope) const;
@ -136,6 +138,8 @@ extern void preload_global_types(void);
* This type is a placeholder for ERROR types.
*/
class VTypeERROR : public VType {
VType*clone() const { return NULL; }
public:
int emit_def(std::ostream&out, perm_string name) const;
};
@ -153,6 +157,8 @@ class VTypePrimitive : public VType {
VTypePrimitive(type_t tt, bool packed = false);
~VTypePrimitive();
VType*clone() const { return new VTypePrimitive(*this); }
void write_to_stream(std::ostream&fd) const;
void show(std::ostream&) const;
@ -189,6 +195,8 @@ class VTypeArray : public VType {
range_t(Expression*m = NULL, Expression*l = NULL, bool dir = true) :
msb_(m), lsb_(l), direction_(dir) { }
range_t*clone() const;
inline bool is_box() const { return msb_==0 && lsb_==0; }
inline bool is_downto() const { return direction_; }
@ -206,6 +214,8 @@ class VTypeArray : public VType {
VTypeArray(const VType*etype, std::list<prange_t*>*r, bool signed_vector =false);
~VTypeArray();
VType*clone() const;
int elaborate(Entity*ent, ScopeBase*scope) const;
void write_to_stream(std::ostream&fd) const;
void write_type_to_stream(std::ostream&fd) const;
@ -246,8 +256,8 @@ class VTypeArray : public VType {
int emit_with_dims_(std::ostream&out, bool packed, perm_string name) const;
void write_range_to_stream_(std::ostream&fd) const;
const VType*etype_;
const VType*etype_;
std::vector<range_t> ranges_;
bool signed_flag_;
const VTypeArray*parent_;
@ -259,6 +269,8 @@ class VTypeRange : public VType {
VTypeRange(const VType*base, int64_t max_val, int64_t min_val);
~VTypeRange();
VType*clone() const { return new VTypeRange(base_->clone(), max_, min_); }
// Get the type that is limited by the range.
inline const VType* base_type() const { return base_; }
@ -277,6 +289,8 @@ class VTypeEnum : public VType {
VTypeEnum(const std::list<perm_string>*names);
~VTypeEnum();
VType*clone() const { return new VTypeEnum(*this); }
void write_to_stream(std::ostream&fd) const;
void show(std::ostream&) const;
int emit_def(std::ostream&out, perm_string name) const;
@ -310,6 +324,8 @@ class VTypeRecord : public VType {
explicit VTypeRecord(std::list<element_t*>*elements);
~VTypeRecord();
VType*clone() const { return new VTypeRecord(*this); }
void write_to_stream(std::ostream&fd) const;
void show(std::ostream&) const;
int emit_def(std::ostream&out, perm_string name) const;
@ -328,6 +344,8 @@ class VTypeDef : public VType {
explicit VTypeDef(perm_string name, const VType*is);
~VTypeDef();
VType*clone() const { return new VTypeDef(*this); }
inline perm_string peek_name() const { return name_; }
// If the type is not given a definition in the constructor,