Permalink
Browse files

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.
  • Loading branch information...
1 parent b80afdf commit b0d61813b23c56c0033d313bbca0ee4282d45bfc @steveicarus committed Mar 11, 2012
Showing with 197 additions and 23 deletions.
  1. +3 −2 Makefile.in
  2. +1 −1 Module.cc
  3. +1 −5 Module.h
  4. +30 −0 PClass.cc
  5. +40 −0 PClass.h
  6. +15 −0 PScope.cc
  7. +19 −0 PScope.h
  8. +9 −6 parse.y
  9. +36 −9 pform.cc
  10. +6 −0 pform.h
  11. +37 −0 pform_pclass.cc
View
@@ -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)
View
@@ -28,7 +28,7 @@ list<Module::named_expr_t> Module::user_defparms;
/* n is a permallocated string. */
Module::Module(perm_string n)
-: PScope(n)
+: PScopeExtra(n)
{
library_flag = false;
is_cell = false;
View
@@ -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<perm_string,PTask*> tasks;
- map<perm_string,PFunction*> funcs;
-
/* The module has a list of generate schemes that appear in
the module definition. These are used at elaboration time. */
list<PGenerate*> generate_schemes;
View
@@ -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()
+{
+}
View
@@ -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
View
@@ -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()
+{
+}
+
View
@@ -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<perm_string,PTask*> tasks;
+ map<perm_string,PFunction*> funcs;
+};
+
#endif
View
15 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;
View
@@ -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<PScopeExtra*> (scope);
+ while (scope && !scopex) {
+ scope = scope->parent_scope();
+ scopex = dynamic_cast<PScopeExtra*> (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<PScopeExtra*> (scope);
+ while (scope && !scopex) {
+ scope = scope->parent_scope();
+ scopex = dynamic_cast<PScopeExtra*> (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<pe
return;
}
- if (class_type_t*class_type = dynamic_cast<class_type_t*> (data_type)) {
+ if (/*class_type_t*class_type =*/ dynamic_cast<class_type_t*> (data_type)) {
VLerror(li, "sorry: Class types not supported.");
return;
}
View
@@ -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<perm_string>*parms,
svector<PWire*>*decl, list<string>*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,
View
@@ -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();
+}

0 comments on commit b0d6181

Please sign in to comment.