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.
This commit is contained in:
parent
b80afdf1f1
commit
b0d61813b2
|
|
@ -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 \
|
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_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 \
|
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 \
|
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 \
|
PGenerate.o PScope.o PSpec.o PTask.o PUdp.o PFunction.o PWire.o \
|
||||||
Statement.o AStatement.o $M $(FF) $(TT)
|
Statement.o AStatement.o $M $(FF) $(TT)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ list<Module::named_expr_t> Module::user_defparms;
|
||||||
|
|
||||||
/* n is a permallocated string. */
|
/* n is a permallocated string. */
|
||||||
Module::Module(perm_string n)
|
Module::Module(perm_string n)
|
||||||
: PScope(n)
|
: PScopeExtra(n)
|
||||||
{
|
{
|
||||||
library_flag = false;
|
library_flag = false;
|
||||||
is_cell = false;
|
is_cell = false;
|
||||||
|
|
|
||||||
6
Module.h
6
Module.h
|
|
@ -49,7 +49,7 @@ class NetScope;
|
||||||
* therefore the handle for grasping the described circuit.
|
* 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
|
/* The module ports are in general a vector of port_t
|
||||||
objects. Each port has a name and an ordered list of
|
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 time_from_timescale;
|
||||||
bool timescale_warn_done;
|
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 has a list of generate schemes that appear in
|
||||||
the module definition. These are used at elaboration time. */
|
the module definition. These are used at elaboration time. */
|
||||||
list<PGenerate*> generate_schemes;
|
list<PGenerate*> generate_schemes;
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
15
PScope.cc
15
PScope.cc
|
|
@ -41,3 +41,18 @@ PWire* LexicalScope::wires_find(perm_string name)
|
||||||
else
|
else
|
||||||
return (*cur).second;
|
return (*cur).second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PScopeExtra::PScopeExtra(perm_string n, LexicalScope*parent)
|
||||||
|
: PScope(n, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PScopeExtra::PScopeExtra(perm_string n)
|
||||||
|
: PScope(n)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PScopeExtra::~PScopeExtra()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
19
PScope.h
19
PScope.h
|
|
@ -27,8 +27,10 @@
|
||||||
|
|
||||||
class PEvent;
|
class PEvent;
|
||||||
class PExpr;
|
class PExpr;
|
||||||
|
class PFunction;
|
||||||
class AProcess;
|
class AProcess;
|
||||||
class PProcess;
|
class PProcess;
|
||||||
|
class PTask;
|
||||||
class PWire;
|
class PWire;
|
||||||
|
|
||||||
class Design;
|
class Design;
|
||||||
|
|
@ -150,4 +152,21 @@ class PScope : public LexicalScope {
|
||||||
perm_string name_;
|
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
|
#endif
|
||||||
|
|
|
||||||
15
parse.y
15
parse.y
|
|
@ -628,18 +628,21 @@ assignment_pattern /* IEEE1800-2005: A.6.7.1 */
|
||||||
|
|
||||||
class_declaration /* IEEE1800-2005: A.1.2 */
|
class_declaration /* IEEE1800-2005: A.1.2 */
|
||||||
: K_virtual_opt K_class class_identifier class_declaration_extends_opt ';'
|
: K_virtual_opt K_class class_identifier class_declaration_extends_opt ';'
|
||||||
class_items_opt K_endclass
|
{ pform_start_class_declaration(@2, $3);
|
||||||
{ // Process a class.
|
|
||||||
if ($4) {
|
if ($4) {
|
||||||
yyerror(@4, "sorry: Class extends not supported yet.");
|
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.");
|
yyerror(@2, "sorry: Class declarations not supported yet.");
|
||||||
}
|
}
|
||||||
class_declaration_endname_opt
|
class_declaration_endname_opt
|
||||||
{ // Wrap up the class.
|
{ // Wrap up the class.
|
||||||
if ($9 && $3 && $3->name != $9) {
|
if ($10 && $3 && $3->name != $10) {
|
||||||
yyerror(@9, "error: Class end name doesn't match class name.");
|
yyerror(@10, "error: Class end name doesn't match class name.");
|
||||||
delete[]$9;
|
delete[]$10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
@ -1348,7 +1351,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
||||||
current_task_set_statement(@3, $7);
|
current_task_set_statement(@3, $7);
|
||||||
pform_pop_scope();
|
pform_pop_scope();
|
||||||
current_task = 0;
|
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.");
|
yyerror(@7, "error: Task body with multiple statements requres SystemVerilog.");
|
||||||
}
|
}
|
||||||
delete $7;
|
delete $7;
|
||||||
|
|
|
||||||
45
pform.cc
45
pform.cc
|
|
@ -23,6 +23,7 @@
|
||||||
# include "pform.h"
|
# include "pform.h"
|
||||||
# include "parse_misc.h"
|
# include "parse_misc.h"
|
||||||
# include "parse_api.h"
|
# include "parse_api.h"
|
||||||
|
# include "PClass.h"
|
||||||
# include "PEvent.h"
|
# include "PEvent.h"
|
||||||
# include "PUdp.h"
|
# include "PUdp.h"
|
||||||
# include "PGenerate.h"
|
# include "PGenerate.h"
|
||||||
|
|
@ -267,12 +268,30 @@ void pform_pop_scope()
|
||||||
lexical_scope = lexical_scope->parent_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)
|
PTask* pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto)
|
||||||
{
|
{
|
||||||
perm_string task_name = lex_strings.make(name);
|
perm_string task_name = lex_strings.make(name);
|
||||||
|
|
||||||
PTask*task = new PTask(task_name, lexical_scope, is_auto);
|
PTask*task = new PTask(task_name, lexical_scope, is_auto);
|
||||||
FILE_NAME(task, loc);
|
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) {
|
if (pform_cur_generate) {
|
||||||
// Check if the task is already in the dictionary.
|
// Check if the task is already in the dictionary.
|
||||||
if (pform_cur_generate->tasks.find(task->pscope_name()) !=
|
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;
|
pform_cur_generate->tasks[task->pscope_name()] = task;
|
||||||
} else {
|
} else {
|
||||||
// Check if the task is already in the dictionary.
|
// Check if the task is already in the dictionary.
|
||||||
if (pform_cur_module->tasks.find(task->pscope_name()) !=
|
if (scopex->tasks.find(task->pscope_name()) != scopex->tasks.end()) {
|
||||||
pform_cur_module->tasks.end()) {
|
|
||||||
cerr << task->get_fileline() << ": error: duplicate "
|
cerr << task->get_fileline() << ": error: duplicate "
|
||||||
"definition for task '" << name << "' in '"
|
"definition for task '" << name << "' in '"
|
||||||
<< pform_cur_module->mod_name() << "'." << endl;
|
<< scopex->pscope_name() << "'." << endl;
|
||||||
error_count += 1;
|
error_count += 1;
|
||||||
}
|
}
|
||||||
pform_cur_module->tasks[task->pscope_name()] = task;
|
scopex->tasks[task->pscope_name()] = task;
|
||||||
}
|
}
|
||||||
|
|
||||||
lexical_scope = task;
|
lexical_scope = task;
|
||||||
|
|
||||||
return 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);
|
PFunction*func = new PFunction(func_name, lexical_scope, is_auto);
|
||||||
FILE_NAME(func, loc);
|
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) {
|
if (pform_cur_generate) {
|
||||||
// Check if the function is already in the dictionary.
|
// Check if the function is already in the dictionary.
|
||||||
if (pform_cur_generate->funcs.find(func->pscope_name()) !=
|
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;
|
pform_cur_generate->funcs[func->pscope_name()] = func;
|
||||||
} else {
|
} else {
|
||||||
// Check if the function is already in the dictionary.
|
// Check if the function is already in the dictionary.
|
||||||
if (pform_cur_module->funcs.find(func->pscope_name()) !=
|
if (scopex->funcs.find(func->pscope_name()) != scopex->funcs.end()) {
|
||||||
pform_cur_module->funcs.end()) {
|
|
||||||
cerr << func->get_fileline() << ": error: duplicate "
|
cerr << func->get_fileline() << ": error: duplicate "
|
||||||
"definition for function '" << name << "' in '"
|
"definition for function '" << name << "' in '"
|
||||||
<< pform_cur_module->mod_name() << "'." << endl;
|
<< scopex->pscope_name() << "'." << endl;
|
||||||
error_count += 1;
|
error_count += 1;
|
||||||
}
|
}
|
||||||
pform_cur_module->funcs[func->pscope_name()] = func;
|
scopex->funcs[func->pscope_name()] = func;
|
||||||
}
|
}
|
||||||
lexical_scope = 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;
|
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.");
|
VLerror(li, "sorry: Class types not supported.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
6
pform.h
6
pform.h
|
|
@ -58,6 +58,7 @@
|
||||||
class PGate;
|
class PGate;
|
||||||
class PExpr;
|
class PExpr;
|
||||||
class PSpecPath;
|
class PSpecPath;
|
||||||
|
class PClass;
|
||||||
struct vlltype;
|
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,
|
extern void pform_endmodule(const char*, bool inside_celldefine,
|
||||||
Module::UCDriveType uc_drive_def);
|
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,
|
extern void pform_make_udp(perm_string name, list<perm_string>*parms,
|
||||||
svector<PWire*>*decl, list<string>*table,
|
svector<PWire*>*decl, list<string>*table,
|
||||||
Statement*init,
|
Statement*init,
|
||||||
|
|
@ -187,6 +192,7 @@ extern void pform_make_udp(perm_string name,
|
||||||
*/
|
*/
|
||||||
extern void pform_pop_scope();
|
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,
|
extern PTask*pform_push_task_scope(const struct vlltype&loc, char*name,
|
||||||
bool is_auto);
|
bool is_auto);
|
||||||
extern PFunction*pform_push_function_scope(const struct vlltype&loc, char*name,
|
extern PFunction*pform_push_function_scope(const struct vlltype&loc, char*name,
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue