diff --git a/elab_scope.cc b/elab_scope.cc index f9753fa77..a0f4c10c2 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -349,13 +349,33 @@ static void blend_class_constructors(PClass*pclass) static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass) { class_type_t*use_type = pclass->type; - netclass_t*use_class = new netclass_t(use_type->name); if (debug_scopes) { cerr << pclass->get_fileline() <<": elaborate_scope_class: " << "Elaborate scope class " << pclass->pscope_name() << endl; } + class_type_t*base_class = dynamic_cast (use_type->base_type); + if (use_type->base_type && !base_class) { + cerr << pclass->get_fileline() << ": error: " + << "Base type of " << use_type->name + << " is not a class." << endl; + des->errors += 1; + } + + netclass_t*use_base_class = 0; + if (base_class) { + use_base_class = scope->find_class(base_class->name); + if (use_base_class == 0) { + cerr << pclass->get_fileline() << ": error: " + << "Base class " << base_class->name + << " not found." << endl; + des->errors += 1; + } + } + + netclass_t*use_class = new netclass_t(use_type->name, use_base_class); + // Class scopes have no parent scope, because references are // not allowed to escape a class method. NetScope*class_scope = new NetScope(0, hname_t(pclass->pscope_name()), diff --git a/netclass.cc b/netclass.cc index 7f2fb97d3..f302585d1 100644 --- a/netclass.cc +++ b/netclass.cc @@ -23,8 +23,8 @@ using namespace std; -netclass_t::netclass_t(perm_string name) -: name_(name), class_scope_(0) +netclass_t::netclass_t(perm_string name, netclass_t*sup) +: name_(name), super_(sup), class_scope_(0) { } @@ -61,43 +61,85 @@ ivl_variable_type_t netclass_t::base_type() const return IVL_VT_CLASS; } +size_t netclass_t::get_properties(void) const +{ + size_t res = properties_.size(); + if (super_) res += super_->get_properties(); + return res; +} + int netclass_t::property_idx_from_name(perm_string pname) const { map::const_iterator cur; cur = properties_.find(pname); - if (cur == properties_.end()) - return -1; + if (cur == properties_.end()) { + if (super_) + return super_->property_idx_from_name(pname); + else + return -1; + } - return cur->second; + int pidx = cur->second; + if (super_) pidx += super_->get_properties(); + return pidx; } const char*netclass_t::get_prop_name(size_t idx) const { - assert(idx < property_table_.size()); - return property_table_[idx].name; + size_t super_size = 0; + if (super_) super_size = super_->get_properties(); + + assert(idx < (super_size + property_table_.size())); + if (idx < super_size) + return super_->get_prop_name(idx); + else + return property_table_[idx-super_size].name; } property_qualifier_t netclass_t::get_prop_qual(size_t idx) const { - assert(idx < property_table_.size()); - return property_table_[idx].qual; + size_t super_size = 0; + if (super_) super_size = super_->get_properties(); + + assert(idx < (super_size+property_table_.size())); + if (idx < super_size) + return super_->get_prop_qual(idx); + else + return property_table_[idx-super_size].qual; } ivl_type_t netclass_t::get_prop_type(size_t idx) const { - assert(idx < property_table_.size()); - return property_table_[idx].type; + size_t super_size = 0; + if (super_) super_size = super_->get_properties(); + + assert(idx < (super_size+property_table_.size())); + if (idx < super_size) + return super_->get_prop_type(idx); + else + return property_table_[idx-super_size].type; } bool netclass_t::get_prop_initialized(size_t idx) const { - assert(idx < property_table_.size()); - return property_table_[idx].initialized_flag; + size_t super_size = 0; + if (super_) super_size = super_->get_properties(); + + assert(idx < (super_size+property_table_.size())); + if (idx < super_size) + return super_->get_prop_initialized(idx); + else + return property_table_[idx].initialized_flag; } void netclass_t::set_prop_initialized(size_t idx) const { - assert(idx < property_table_.size()); + size_t super_size = 0; + if (super_) super_size = super_->get_properties(); + + assert(idx >= super_size && idx < (super_size+property_table_.size())); + idx -= super_size; + assert(! property_table_[idx].initialized_flag); property_table_[idx].initialized_flag = true; } diff --git a/netclass.h b/netclass.h index 56039a56c..79e912f74 100644 --- a/netclass.h +++ b/netclass.h @@ -33,7 +33,7 @@ class PClass; class netclass_t : public ivl_type_s { public: - netclass_t(perm_string class_name); + netclass_t(perm_string class_name, netclass_t*par); ~netclass_t(); // Set the property of the class during elaboration. Set the @@ -52,7 +52,13 @@ class netclass_t : public ivl_type_s { // This is the name of the class type inline perm_string get_name() const { return name_; } - inline size_t get_properties(void) const { return properties_.size(); } + // If this is derived from another class, then this method + // returns a pointer to the super-class. + inline const netclass_t* get_super() const { return super_; } + + // Get the number of properties in this class. Include + // properties in the parent class. + size_t get_properties(void) const; // Get information about each property. const char*get_prop_name(size_t idx) const; property_qualifier_t get_prop_qual(size_t idx) const; @@ -92,6 +98,9 @@ class netclass_t : public ivl_type_s { private: perm_string name_; + // If this is derived from another base class, point to it + // here. + netclass_t*super_; // Map properrty names to property table index. std::map properties_; // Vector of properties. diff --git a/parse.y b/parse.y index 393aa6d10..5baf61dc7 100644 --- a/parse.y +++ b/parse.y @@ -683,11 +683,7 @@ assignment_pattern /* IEEE1800-2005: A.6.7.1 */ class_declaration /* IEEE1800-2005: A.1.2 */ : K_virtual_opt K_class class_identifier class_declaration_extends_opt ';' - { pform_start_class_declaration(@2, $3); - if ($4) { - yyerror(@4, "sorry: Class extends not supported yet."); - } - } + { pform_start_class_declaration(@2, $3, $4); } class_items_opt K_endclass { // Process a class. pform_end_class_declaration(@8); diff --git a/pform.h b/pform.h index 6eaf170ff..70db36c87 100644 --- a/pform.h +++ b/pform.h @@ -181,7 +181,8 @@ extern void pform_endmodule(const char*, bool inside_celldefine, Module::UCDriveType uc_drive_def); extern void pform_start_class_declaration(const struct vlltype&loc, - class_type_t*type); + class_type_t*type, + data_type_t*base_type); extern void pform_class_property(const struct vlltype&loc, property_qualifier_t pq, data_type_t*data_type, diff --git a/pform_dump.cc b/pform_dump.cc index a744b3c96..9a02c9d2d 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -182,12 +182,16 @@ void class_type_t::pform_dump(ostream&out, unsigned indent) const { out << setw(indent) << "" << "class " << name << " {"; + if (base_type) out << " (extends)"; + for (map::const_iterator cur = properties.begin() ; cur != properties.end() ; ++cur) { out << " " << cur->first; } out << " }" << endl; + + if (base_type) base_type->pform_dump(out, indent+4); } void class_type_t::pform_dump_init(ostream&out, unsigned indent) const diff --git a/pform_pclass.cc b/pform_pclass.cc index f82b8120b..f3da71dda 100644 --- a/pform_pclass.cc +++ b/pform_pclass.cc @@ -26,12 +26,15 @@ */ static PClass*pform_cur_class = 0; -void pform_start_class_declaration(const struct vlltype&loc, class_type_t*type) +void pform_start_class_declaration(const struct vlltype&loc, class_type_t*type, data_type_t*base_type) { PClass*class_scope = pform_push_class_scope(loc, type->name); class_scope->type = type; assert(pform_cur_class == 0); pform_cur_class = class_scope; + + assert(type->base_type == 0); + type->base_type = base_type; } void pform_class_property(const struct vlltype&loc, diff --git a/pform_types.h b/pform_types.h index f8ba0e172..5619e6d39 100644 --- a/pform_types.h +++ b/pform_types.h @@ -225,13 +225,19 @@ struct string_type_t : public data_type_t { struct class_type_t : public data_type_t { inline explicit class_type_t(perm_string n) - : name(n) { } + : name(n), base_type(0) { } void pform_dump(std::ostream&out, unsigned indent) const; void pform_dump_init(std::ostream&out, unsigned indent) const; // This is the name of the class type. perm_string name; + + // This is the named type that is supposed to be the base + // class that we are extending. This is nil if there is no + // hierarchy. + data_type_t*base_type; + // This is a map of the properties. Map the name to the type. struct prop_info_t { inline prop_info_t() : qual(property_qualifier_t::make_none()), type(0) { }