From b0d61813b23c56c0033d313bbca0ee4282d45bfc Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 11 Mar 2012 13:18:24 -0700 Subject: [PATCH] Get the scope of class methods right Class methods belong in a class scope, not the containing module. So create a lexical scope that carries tasks and functions and create a PClass to represent classes. --- Makefile.in | 5 +++-- Module.cc | 2 +- Module.h | 6 +----- PClass.cc | 30 ++++++++++++++++++++++++++++++ PClass.h | 40 ++++++++++++++++++++++++++++++++++++++++ PScope.cc | 15 +++++++++++++++ PScope.h | 19 +++++++++++++++++++ parse.y | 15 +++++++++------ pform.cc | 45 ++++++++++++++++++++++++++++++++++++--------- pform.h | 6 ++++++ pform_pclass.cc | 37 +++++++++++++++++++++++++++++++++++++ 11 files changed, 197 insertions(+), 23 deletions(-) create mode 100644 PClass.cc create mode 100644 PClass.h create mode 100644 pform_pclass.cc diff --git a/Makefile.in b/Makefile.in index ba3663735f..7bd62d4f1f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -110,9 +110,10 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \ netenum.o netstruct.o net_event.o net_expr.o net_func.o net_link.o net_modulo.o \ net_nex_input.o net_nex_output.o net_proc.o net_scope.o net_tran.o \ net_udp.o pad_to_width.o parse.o parse_misc.o pform.o pform_analog.o \ - pform_disciplines.o pform_dump.o pform_struct_type.o pform_types.o \ + pform_disciplines.o pform_dump.o pform_pclass.o pform_struct_type.o \ + pform_types.o \ symbol_search.o sync.o sys_funcs.o verinum.o verireal.o target.o \ - Attrib.o HName.o Module.o PDelays.o PEvent.o PExpr.o PGate.o \ + Attrib.o HName.o Module.o PClass.o PDelays.o PEvent.o PExpr.o PGate.o \ PGenerate.o PScope.o PSpec.o PTask.o PUdp.o PFunction.o PWire.o \ Statement.o AStatement.o $M $(FF) $(TT) diff --git a/Module.cc b/Module.cc index 40871d059d..66efe26b04 100644 --- a/Module.cc +++ b/Module.cc @@ -28,7 +28,7 @@ list Module::user_defparms; /* n is a permallocated string. */ Module::Module(perm_string n) -: PScope(n) +: PScopeExtra(n) { library_flag = false; is_cell = false; diff --git a/Module.h b/Module.h index 307836edf2..a791a6be2d 100644 --- a/Module.h +++ b/Module.h @@ -49,7 +49,7 @@ class NetScope; * therefore the handle for grasping the described circuit. */ -class Module : public PScope, public LineInfo { +class Module : public PScopeExtra, public LineInfo { /* The module ports are in general a vector of port_t objects. Each port has a name and an ordered list of @@ -112,10 +112,6 @@ class Module : public PScope, public LineInfo { bool time_from_timescale; bool timescale_warn_done; - /* Task definitions within this module */ - map tasks; - map funcs; - /* The module has a list of generate schemes that appear in the module definition. These are used at elaboration time. */ list generate_schemes; diff --git a/PClass.cc b/PClass.cc new file mode 100644 index 0000000000..9a9a623553 --- /dev/null +++ b/PClass.cc @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2012 Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +# include "PClass.h" + +PClass::PClass(perm_string name, LexicalScope*parent) +: PScopeExtra(name, parent) +{ +} + + +PClass::~PClass() +{ +} diff --git a/PClass.h b/PClass.h new file mode 100644 index 0000000000..b4578ad685 --- /dev/null +++ b/PClass.h @@ -0,0 +1,40 @@ +#ifndef __PClass_H +#define __PClass_H +/* + * Copyright (c) 2012 Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +# include "PScope.h" +# include "LineInfo.h" +# include "StringHeap.h" + +/* + * SystemVerilog supports class declarations with their own lexical + * scope, etc. The parser arranges for these to be created and + * collected. + */ + +class PClass : public PScopeExtra, public LineInfo { + + public: + explicit PClass (perm_string name, LexicalScope*parent); + ~PClass(); + +}; + +#endif diff --git a/PScope.cc b/PScope.cc index f23a506eeb..0e5dd4abe8 100644 --- a/PScope.cc +++ b/PScope.cc @@ -41,3 +41,18 @@ PWire* LexicalScope::wires_find(perm_string name) else return (*cur).second; } + +PScopeExtra::PScopeExtra(perm_string n, LexicalScope*parent) +: PScope(n, parent) +{ +} + +PScopeExtra::PScopeExtra(perm_string n) +: PScope(n) +{ +} + +PScopeExtra::~PScopeExtra() +{ +} + diff --git a/PScope.h b/PScope.h index d2b0feb537..e14cb6b4eb 100644 --- a/PScope.h +++ b/PScope.h @@ -27,8 +27,10 @@ class PEvent; class PExpr; +class PFunction; class AProcess; class PProcess; +class PTask; class PWire; class Design; @@ -150,4 +152,21 @@ class PScope : public LexicalScope { perm_string name_; }; +/* + * Some scopes can carry definitions. These include Modules and PClass + * scopes. These derive from PScopeExtra so that they hold the maps of + * extra definitions. + */ +class PScopeExtra : public PScope { + + public: + PScopeExtra(perm_string, LexicalScope*parent); + PScopeExtra(perm_string); + ~PScopeExtra(); + + /* Task definitions within this module */ + map tasks; + map funcs; +}; + #endif diff --git a/parse.y b/parse.y index 5be1b2eca5..6b97c63648 100644 --- a/parse.y +++ b/parse.y @@ -628,18 +628,21 @@ 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 ';' - class_items_opt K_endclass - { // Process a class. + { pform_start_class_declaration(@2, $3); if ($4) { yyerror(@4, "sorry: Class extends not supported yet."); } + } + class_items_opt K_endclass + { // Process a class. + pform_end_class_declaration(); yyerror(@2, "sorry: Class declarations not supported yet."); } class_declaration_endname_opt { // Wrap up the class. - if ($9 && $3 && $3->name != $9) { - yyerror(@9, "error: Class end name doesn't match class name."); - delete[]$9; + if ($10 && $3 && $3->name != $10) { + yyerror(@10, "error: Class end name doesn't match class name."); + delete[]$10; } } ; @@ -1348,7 +1351,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */ current_task_set_statement(@3, $7); pform_pop_scope(); current_task = 0; - if ($7->size() > 1 && !gn_system_verilog()) { + if ($7 && $7->size() > 1 && !gn_system_verilog()) { yyerror(@7, "error: Task body with multiple statements requres SystemVerilog."); } delete $7; diff --git a/pform.cc b/pform.cc index a8569ff01b..d348778554 100644 --- a/pform.cc +++ b/pform.cc @@ -23,6 +23,7 @@ # include "pform.h" # include "parse_misc.h" # include "parse_api.h" +# include "PClass.h" # include "PEvent.h" # include "PUdp.h" # include "PGenerate.h" @@ -267,12 +268,30 @@ void pform_pop_scope() lexical_scope = lexical_scope->parent_scope(); } +PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name) +{ + PClass*class_scope = new PClass(name, lexical_scope); + FILE_NAME(class_scope, loc); + + lexical_scope = class_scope; + return class_scope; +} + PTask* pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto) { perm_string task_name = lex_strings.make(name); PTask*task = new PTask(task_name, lexical_scope, is_auto); FILE_NAME(task, loc); + + LexicalScope*scope = lexical_scope; + PScopeExtra*scopex = dynamic_cast (scope); + while (scope && !scopex) { + scope = scope->parent_scope(); + scopex = dynamic_cast (scope); + } + assert(scopex); + if (pform_cur_generate) { // Check if the task is already in the dictionary. if (pform_cur_generate->tasks.find(task->pscope_name()) != @@ -286,15 +305,15 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto) pform_cur_generate->tasks[task->pscope_name()] = task; } else { // Check if the task is already in the dictionary. - if (pform_cur_module->tasks.find(task->pscope_name()) != - pform_cur_module->tasks.end()) { + if (scopex->tasks.find(task->pscope_name()) != scopex->tasks.end()) { cerr << task->get_fileline() << ": error: duplicate " "definition for task '" << name << "' in '" - << pform_cur_module->mod_name() << "'." << endl; + << scopex->pscope_name() << "'." << endl; error_count += 1; } - pform_cur_module->tasks[task->pscope_name()] = task; + scopex->tasks[task->pscope_name()] = task; } + lexical_scope = task; return task; @@ -307,6 +326,15 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, char*name, PFunction*func = new PFunction(func_name, lexical_scope, is_auto); FILE_NAME(func, loc); + + LexicalScope*scope = lexical_scope; + PScopeExtra*scopex = dynamic_cast (scope); + while (scope && !scopex) { + scope = scope->parent_scope(); + scopex = dynamic_cast (scope); + } + assert(scopex); + if (pform_cur_generate) { // Check if the function is already in the dictionary. if (pform_cur_generate->funcs.find(func->pscope_name()) != @@ -320,14 +348,13 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, char*name, pform_cur_generate->funcs[func->pscope_name()] = func; } else { // Check if the function is already in the dictionary. - if (pform_cur_module->funcs.find(func->pscope_name()) != - pform_cur_module->funcs.end()) { + if (scopex->funcs.find(func->pscope_name()) != scopex->funcs.end()) { cerr << func->get_fileline() << ": error: duplicate " "definition for function '" << name << "' in '" - << pform_cur_module->mod_name() << "'." << endl; + << scopex->pscope_name() << "'." << endl; error_count += 1; } - pform_cur_module->funcs[func->pscope_name()] = func; + scopex->funcs[func->pscope_name()] = func; } lexical_scope = func; @@ -2640,7 +2667,7 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list (data_type)) { + if (/*class_type_t*class_type =*/ dynamic_cast (data_type)) { VLerror(li, "sorry: Class types not supported."); return; } diff --git a/pform.h b/pform.h index 6af3053146..941f5f7d3c 100644 --- a/pform.h +++ b/pform.h @@ -58,6 +58,7 @@ class PGate; class PExpr; class PSpecPath; +class PClass; struct vlltype; /* @@ -168,6 +169,10 @@ extern Module::port_t* pform_module_port_reference(perm_string name, 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); +extern void pform_end_class_declaration(void); + extern void pform_make_udp(perm_string name, list*parms, svector*decl, list*table, Statement*init, @@ -187,6 +192,7 @@ extern void pform_make_udp(perm_string name, */ extern void pform_pop_scope(); +extern PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name); extern PTask*pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto); extern PFunction*pform_push_function_scope(const struct vlltype&loc, char*name, diff --git a/pform_pclass.cc b/pform_pclass.cc new file mode 100644 index 0000000000..935734a622 --- /dev/null +++ b/pform_pclass.cc @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2012 Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +# include "pform.h" +# include "PClass.h" + +static PClass*pform_cur_class = 0; + +void pform_start_class_declaration(const struct vlltype&loc, class_type_t*type) +{ + PClass*class_scope = pform_push_class_scope(loc, type->name); + assert(pform_cur_class == 0); + pform_cur_class = class_scope; +} + +void pform_end_class_declaration(void) +{ + assert(pform_cur_class); + pform_cur_class = 0; + pform_pop_scope(); +}