diff --git a/PFunction.cc b/PFunction.cc index d2468145b..47ac34b6a 100644 --- a/PFunction.cc +++ b/PFunction.cc @@ -22,7 +22,7 @@ # include PFunction::PFunction(perm_string name, LexicalScope*parent, bool is_auto__) -: PScope(name, parent), this_type_(0), ports_(0), statement_(0) +: PTaskFunc(name, parent), ports_(0), statement_(0) { is_auto_ = is_auto__; return_type_.type = PTF_NONE; @@ -32,12 +32,6 @@ PFunction::~PFunction() { } -void PFunction::set_this(class_type_t*use_type) -{ - assert(this_type_ == 0); - this_type_ = use_type; -} - void PFunction::set_ports(vector*p) { assert(ports_ == 0); diff --git a/PTask.cc b/PTask.cc index 31297fa35..e3c2e542b 100644 --- a/PTask.cc +++ b/PTask.cc @@ -21,8 +21,23 @@ # include "PTask.h" # include +PTaskFunc::PTaskFunc(perm_string n, LexicalScope*p) +: PScope(n,p), this_type_(0) +{ +} + +PTaskFunc::~PTaskFunc() +{ +} + +void PTaskFunc::set_this(class_type_t*type) +{ + assert(this_type_ == 0); + this_type_ = type; +} + PTask::PTask(perm_string name, LexicalScope*parent, bool is_auto__) -: PScope(name, parent), this_type_(0), ports_(0), statement_(0) +: PTaskFunc(name, parent), ports_(0), statement_(0) { is_auto_ = is_auto__; } @@ -31,12 +46,6 @@ PTask::~PTask() { } -void PTask::set_this(class_type_t*type) -{ - assert(this_type_ == 0); - this_type_ = type; -} - void PTask::set_ports(vector*p) { assert(ports_ == 0); diff --git a/PTask.h b/PTask.h index 01893e122..e590f3cad 100644 --- a/PTask.h +++ b/PTask.h @@ -50,16 +50,31 @@ struct PTaskFuncArg { std::list*range; }; +class PTaskFunc : public PScope, public LineInfo { + + public: + PTaskFunc(perm_string name, LexicalScope*parent); + ~PTaskFunc(); + + void set_this(class_type_t*use_type); + + // If this task is a method of a class, this returns a pointer + // to the class type. + inline class_type_t* method_of() const { return this_type_; } + + private: + class_type_t*this_type_; +}; + /* * The PTask holds the parsed definitions of a task. */ -class PTask : public PScope, public LineInfo { +class PTask : public PTaskFunc { public: explicit PTask(perm_string name, LexicalScope*parent, bool is_auto); ~PTask(); - void set_this(class_type_t*use_type); void set_ports(std::vector*p); void set_statement(Statement *s); @@ -77,14 +92,9 @@ class PTask : public PScope, public LineInfo { bool is_auto() const { return is_auto_; }; - // If this task is a method of a class, this returns a pointer - // to the class type. - inline class_type_t* method_of() const { return this_type_; } - void dump(ostream&, unsigned) const; private: - class_type_t*this_type_; std::vector*ports_; Statement*statement_; bool is_auto_; @@ -101,13 +111,12 @@ class PTask : public PScope, public LineInfo { * * The output value is not elaborated until elaborate_sig. */ -class PFunction : public PScope, public LineInfo { +class PFunction : public PTaskFunc { public: explicit PFunction(perm_string name, LexicalScope*parent, bool is_auto); ~PFunction(); - void set_this(class_type_t*use_type); void set_ports(std::vector*p); void set_statement(Statement *s); void set_return(PTaskFuncArg t); @@ -122,14 +131,9 @@ class PFunction : public PScope, public LineInfo { bool is_auto() const { return is_auto_; }; - // If this function is a method of a class, this returns a - // pointer to the class type. - inline class_type_t* method_of() const { return this_type_; } - void dump(ostream&, unsigned) const; private: - class_type_t*this_type_; PTaskFuncArg return_type_; std::vector *ports_; Statement *statement_; diff --git a/elab_scope.cc b/elab_scope.cc index 6131496f9..a1f584e0c 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -302,6 +302,18 @@ static void elaborate_scope_class(Design*des, NetScope*scope, use_class->set_property(cur->first, tmp); } + for (map::iterator cur = pclass->tasks.begin() + ; cur != pclass->tasks.end() ; ++cur) { + cerr << cur->second->get_fileline() << ": sorry: " + << "Class methods (tasks) not supported." << endl; + } + + for (map::iterator cur = pclass->funcs.begin() + ; cur != pclass->funcs.end() ; ++cur) { + cerr << cur->second->get_fileline() << ": sorry: " + << "Class methods (functions) not supported." << endl; + } + scope->add_class(use_class); } diff --git a/parse.y b/parse.y index 37b7d41eb..3733513bf 100644 --- a/parse.y +++ b/parse.y @@ -60,6 +60,19 @@ static PTask* current_task = 0; static PFunction* current_function = 0; static stack current_block_stack; +static pform_name_t* pform_create_this(void) +{ + name_component_t name (perm_string::literal("@")); + pform_name_t*res = new pform_name_t; + res->push_back(name); + return res; +} + +static pform_name_t* pform_create_super(void) +{ + return 0; +} + /* This is used to keep track of the extra arguments after the notifier * in the $setuphold and $recrem timing checks. This allows us to print * a warning message that the delayed signals will not be created. We @@ -544,9 +557,10 @@ static void current_function_set_statement(const YYLTYPE&loc, vector %type gate_instance %type gate_instance_list -%type hierarchy_identifier +%type hierarchy_identifier implicit_class_handle %type assignment_pattern expression expr_primary expr_mintypmax -%type class_new dynamic_array_new inc_or_dec_expression inside_expression lpvalue +%type class_new dynamic_array_new +%type inc_or_dec_expression inside_expression lpvalue %type branch_probe_expression streaming_concatenation %type delay_value delay_value_simple %type delay1 delay3 delay3_opt delay_value_list @@ -771,14 +785,10 @@ class_item /* IEEE1800-2005: A.1.8 */ /* Class methods... */ | method_qualifier_opt task_declaration - { yyerror(@2, "sorry: Class methods (tasks) not supported yet."); - yyerrok; - } + { /* The task_declaration rule puts this into the class */ } | method_qualifier_opt function_declaration - { yyerror(@2, "sorry: Class methods (functions) not supported yet."); - yyerrok; - } + { /* The function_declaration rule puts this into the class */ } /* Class constraints... */ @@ -1095,8 +1105,8 @@ function_declaration /* IEEE1800-2005: A.2.6 */ ; implicit_class_handle /* IEEE1800-2005: A.8.4 */ - : K_this - | K_super + : K_this { $$ = pform_create_this(); } + | K_super { $$ = pform_create_super(); } ; /* SystemVerilog adds support for the increment/decrement @@ -3015,13 +3025,23 @@ expr_primary } | implicit_class_handle - { yyerror(@1, "sorry: Implicit class handles (this/super) are not supported."); - $$ = 0; + { PEIdent*tmp = new PEIdent(*$1); + FILE_NAME(tmp,@1); + delete $1; + $$ = tmp; } | implicit_class_handle '.' hierarchy_identifier - { yyerror(@1, "sorry: Implicit class handles (this/super) are not supported."); - $$ = 0; + { pform_name_t*nam = $1; + while (! $3->empty()) { + nam->push_back($3->front()); + $3->pop_front(); + } + PEIdent*tmp = new PEIdent(*nam); + FILE_NAME(tmp,@1); + delete $1; + delete $3; + $$ = tmp; } /* Many of the VAMS built-in functions are available as builtin @@ -3821,10 +3841,15 @@ lpvalue } | implicit_class_handle '.' hierarchy_identifier - { yyerror(@1, "sorry: implicit class handles (this/super) not supported."); - PEIdent*tmp = new PEIdent(*$3); + { pform_name_t*tmp1 = $1; + while (!$3->empty()) { + tmp1->push_back($3->front()); + $3->pop_front(); + } + PEIdent*tmp = new PEIdent(*tmp1); FILE_NAME(tmp, @1); $$ = tmp; + delete tmp1; delete $3; } diff --git a/pform.h b/pform.h index cf8037c66..4f6174f0a 100644 --- a/pform.h +++ b/pform.h @@ -185,8 +185,8 @@ extern void pform_class_property(const struct vlltype&loc, property_qualifier_t pq, data_type_t*data_type, std::list*decls); -extern void pform_set_this_class(PFunction*net); -extern void pform_set_this_class(PTask*net); +extern void pform_set_this_class(PTaskFunc*net); + extern void pform_end_class_declaration(void); extern void pform_make_udp(perm_string name, list*parms, diff --git a/pform_dump.cc b/pform_dump.cc index 408074041..2978ed816 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -908,8 +908,8 @@ void PFunction::dump(ostream&out, unsigned ind) const } out << pscope_name() << ";" << endl; - if (this_type_) - out << setw(ind) << "" << "method of " << this_type_->name << ";" << endl; + if (method_of()) + out << setw(ind) << "" << "method of " << method_of()->name << ";" << endl; if (ports_) for (unsigned idx = 0 ; idx < ports_->size() ; idx += 1) { @@ -949,8 +949,8 @@ void PTask::dump(ostream&out, unsigned ind) const out << setw(ind) << "" << "task "; if (is_auto_) cout << "automatic "; out << pscope_name() << ";" << endl; - if (this_type_) - out << setw(ind) << "" << "method of " << this_type_->name << ";" << endl; + if (method_of()) + out << setw(ind) << "" << "method of " << method_of()->name << ";" << endl; if (ports_) for (unsigned idx = 0 ; idx < ports_->size() ; idx += 1) { if ((*ports_)[idx] == 0) { diff --git a/pform_pclass.cc b/pform_pclass.cc index 188911398..6b23c57e6 100644 --- a/pform_pclass.cc +++ b/pform_pclass.cc @@ -72,15 +72,7 @@ void pform_class_property(const struct vlltype&loc, } } -void pform_set_this_class(PFunction*net) -{ - if (pform_cur_class == 0) - return; - - net->set_this(pform_cur_class->type); -} - -void pform_set_this_class(PTask*net) +void pform_set_this_class(PTaskFunc*net) { if (pform_cur_class == 0) return;