diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 69c0485f7..74e143c63 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -40,7 +40,7 @@ Expression::~Expression() void Expression::set_type(const VType*typ) { - assert(type_ == 0); + assert(type_==0 || type_==typ); type_ = typ; } diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 233afc0fe..e5c143e3e 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -193,6 +193,9 @@ class ExpBinary : public Expression { void dump_operands(ostream&out, int indent = 0) const; + private: + virtual const VType*resolve_operand_types_(const VType*t1, const VType*t2) const; + private: Expression*operand1_; Expression*operand2_; @@ -305,6 +308,9 @@ class ExpArithmetic : public ExpBinary { virtual bool evaluate(ScopeBase*scope, int64_t&val) const; void dump(ostream&out, int indent = 0) const; + private: + const VType* resolve_operand_types_(const VType*t1, const VType*t2) const; + private: fun_t fun_; }; diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index f88bdbb03..2ca201d35 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -328,6 +328,9 @@ const VType* ExpBinary::probe_type(Entity*ent, Architecture*arc) const if (t1 == t2) return t1; + if (const VType*tb = resolve_operand_types_(t1, t2)) + return tb; + // FIXME: I should at this point try harder to find an // operator that has the proper argument list and use this // here, but for now we leave it for the back-end to figure out. @@ -337,6 +340,11 @@ const VType* ExpBinary::probe_type(Entity*ent, Architecture*arc) const return 0; } +const VType*ExpBinary::resolve_operand_types_(const VType*t1, const VType*t2) const +{ + return 0; +} + int ExpBinary::elaborate_exprs(Entity*ent, Architecture*arc, const VType*ltype) { int errors = 0; @@ -491,6 +499,21 @@ int ExpArithmetic::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltyp return errors; } +const VType* ExpArithmetic::resolve_operand_types_(const VType*t1, const VType*t2) const +{ + while (const VTypeRange*tmp = dynamic_cast (t1)) + t1 = tmp->base_type(); + while (const VTypeRange*tmp = dynamic_cast (t2)) + t2 = tmp->base_type(); + + if (t1->type_match(t2)) + return t1; + if (t2->type_match(t2)) + return t2; + + return 0; +} + const VType* ExpAttribute::probe_type(Entity*ent, Architecture*arc) const { base_->probe_type(ent, arc); diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 0c33b2566..e18e9ecbd 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -205,6 +205,10 @@ class VTypeRange : public VType { VTypeRange(const VType*base, int64_t max_val, int64_t min_val); ~VTypeRange(); + // Get the type that is limited by the range. + inline const VType* base_type() const { return base_; } + + public: // Virtual methods void write_to_stream(std::ostream&fd) const; int emit_def(std::ostream&out) const;