Rework of lexical scope handling in parser.

This patch modifies the parser to use a single stack to track lexical
scopes, rather than starting a new stack for each generate construct.
This commit is contained in:
Martin Whitaker 2010-01-08 22:49:48 +00:00 committed by Stephen Williams
parent 6eb5f593f0
commit b4f070e60b
11 changed files with 77 additions and 124 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2008,2010 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
@ -21,7 +21,7 @@
#include "PTask.h"
PFunction::PFunction(perm_string name, PScope*parent, bool is_auto__)
PFunction::PFunction(perm_string name, LexicalScope*parent, bool is_auto__)
: PScope(name, parent), ports_(0), statement_(0)
{
is_auto_ = is_auto__;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006,2009 Stephen Williams (steve@icarus.com)
* Copyright (c) 2006,2009,2010 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
@ -21,12 +21,10 @@
# include "PWire.h"
# include "ivl_assert.h"
PGenerate::PGenerate(unsigned id)
: id_number(id)
PGenerate::PGenerate(LexicalScope*parent, unsigned id)
: LexicalScope(parent), id_number(id)
{
direct_nested_ = false;
parent = 0;
lexical_scope = 0;
}
PGenerate::~PGenerate()

View File

@ -1,7 +1,7 @@
#ifndef __PGenerate_H
#define __PGenerate_H
/*
* Copyright (c) 2006-2009 Stephen Williams (steve@icarus.com)
* Copyright (c) 2006-2010 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
@ -53,7 +53,7 @@ class PWire;
class PGenerate : public LineInfo, public LexicalScope {
public:
explicit PGenerate(unsigned id_number);
explicit PGenerate(LexicalScope*parent, unsigned id_number);
~PGenerate();
// Generate schemes have an ID number, for when the scope is
@ -63,7 +63,7 @@ class PGenerate : public LineInfo, public LexicalScope {
// This is used during parsing to stack lexical scopes within
// this generate scheme.
PScope*lexical_scope;
// LexicalScope*lexical_scope;
enum scheme_t {GS_NONE, GS_LOOP, GS_CONDIT, GS_ELSE,
GS_CASE, GS_CASE_ITEM, GS_NBLOCK};
@ -92,7 +92,7 @@ class PGenerate : public LineInfo, public LexicalScope {
// Generate schemes can contain further generate schemes.
list<PGenerate*> generate_schemes;
PGenerate*parent;
// PGenerate*parent;
// This method is called by the elaboration of a module to
// generate scopes. the container is the scope that is to

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2008,2010 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
@ -19,13 +19,13 @@
# include "PScope.h"
PScope::PScope(perm_string n, PScope*parent)
: name_(n), parent_(parent)
PScope::PScope(perm_string n, LexicalScope*parent)
: LexicalScope(parent), name_(n)
{
}
PScope::PScope(perm_string n)
: name_(n), parent_(0)
: LexicalScope(0), name_(n)
{
}

View File

@ -1,7 +1,7 @@
#ifndef __PScope_H
#define __PScope_H
/*
* Copyright (c) 2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2008,2010 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
@ -46,7 +46,7 @@ class NetScope;
class LexicalScope {
public:
explicit LexicalScope() { }
explicit LexicalScope(LexicalScope*parent) : parent_(parent) { }
// A virtual destructor is so that dynamic_cast can work.
virtual ~LexicalScope() { }
@ -94,6 +94,8 @@ class LexicalScope {
list<PProcess*> behaviors;
list<AProcess*> analog_behaviors;
LexicalScope* parent_scope() const { return parent_; }
protected:
void dump_parameters_(ostream&out, unsigned indent) const;
@ -104,6 +106,7 @@ class LexicalScope {
void dump_wires_(ostream&out, unsigned indent) const;
private:
LexicalScope*parent_;
};
class PScope : public LexicalScope {
@ -117,12 +120,11 @@ class PScope : public LexicalScope {
// modules do not nest in Verilog, the parent must be nil for
// modules. Scopes for tasks and functions point to their
// containing module.
PScope(perm_string name, PScope*parent);
PScope(perm_string name, LexicalScope*parent);
PScope(perm_string name);
virtual ~PScope();
perm_string pscope_name() const { return name_; }
PScope* pscope_parent() { return parent_; }
protected:
bool elaborate_sig_wires_(Design*des, NetScope*scope) const;
@ -131,7 +133,6 @@ class PScope : public LexicalScope {
private:
perm_string name_;
PScope*parent_;
};
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2008,2010 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
@ -21,7 +21,7 @@
# include "PTask.h"
PTask::PTask(perm_string name, PScope*parent, bool is_auto__)
PTask::PTask(perm_string name, LexicalScope*parent, bool is_auto__)
: PScope(name, parent), ports_(0), statement_(0)
{
is_auto_ = is_auto__;

View File

@ -1,7 +1,7 @@
#ifndef __PTask_H
#define __PTask_H
/*
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2008,2010 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
@ -51,7 +51,7 @@ struct PTaskFuncArg {
class PTask : public PScope, public LineInfo {
public:
explicit PTask(perm_string name, PScope*parent, bool is_auto);
explicit PTask(perm_string name, LexicalScope*parent, bool is_auto);
~PTask();
void set_ports(svector<PWire *>*p);
@ -93,7 +93,7 @@ class PTask : public PScope, public LineInfo {
class PFunction : public PScope, public LineInfo {
public:
explicit PFunction(perm_string name, PScope*parent, bool is_auto);
explicit PFunction(perm_string name, LexicalScope*parent, bool is_auto);
~PFunction();
void set_ports(svector<PWire *>*p);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2008,2010 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
@ -93,7 +93,7 @@ PAssignNB::~PAssignNB()
{
}
PBlock::PBlock(perm_string n, PScope*parent, BL_TYPE t)
PBlock::PBlock(perm_string n, LexicalScope*parent, BL_TYPE t)
: PScope(n, parent), bl_type_(t)
{
}

View File

@ -159,7 +159,7 @@ class PBlock : public PScope, public Statement {
enum BL_TYPE { BL_SEQ, BL_PAR };
// If the block has a name, it is a scope and also has a parent.
explicit PBlock(perm_string n, PScope*parent, BL_TYPE t);
explicit PBlock(perm_string n, LexicalScope*parent, BL_TYPE t);
// If it doesn't have a name, it's not a scope
explicit PBlock(BL_TYPE t);
~PBlock();

142
pform.cc
View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2009 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2010 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
@ -258,29 +258,20 @@ static inline void FILE_NAME(LineInfo*obj, const char*file, unsigned lineno)
*
* Items that have scoped names are put in the lexical_scope object.
*/
static PScope* lexical_scope = 0;
static LexicalScope* lexical_scope = 0;
void pform_pop_scope()
{
if (pform_cur_generate) {
assert(pform_cur_generate->lexical_scope);
PScope*cur = pform_cur_generate->lexical_scope;
pform_cur_generate->lexical_scope = cur->pscope_parent();
} else {
assert(lexical_scope);
lexical_scope = lexical_scope->pscope_parent();
}
lexical_scope = lexical_scope->parent_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;
PTask*task = new PTask(task_name, lexical_scope, is_auto);
FILE_NAME(task, loc);
if (pform_cur_generate) {
task = new PTask(task_name, pform_cur_generate->lexical_scope,
is_auto);
FILE_NAME(task, loc);
// Check if the task is already in the dictionary.
if (pform_cur_generate->tasks.find(task->pscope_name()) !=
pform_cur_generate->tasks.end()) {
@ -291,11 +282,7 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto)
error_count += 1;
}
pform_cur_generate->tasks[task->pscope_name()] = task;
pform_cur_generate->lexical_scope = task;
} else {
task = new PTask(task_name, lexical_scope,
is_auto);
FILE_NAME(task, loc);
// Check if the task is already in the dictionary.
if (pform_cur_module->tasks.find(task->pscope_name()) !=
pform_cur_module->tasks.end()) {
@ -305,8 +292,8 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto)
error_count += 1;
}
pform_cur_module->tasks[task->pscope_name()] = task;
lexical_scope = task;
}
lexical_scope = task;
return task;
}
@ -316,11 +303,9 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, char*name,
{
perm_string func_name = lex_strings.make(name);
PFunction*func;
PFunction*func = new PFunction(func_name, lexical_scope, is_auto);
FILE_NAME(func, loc);
if (pform_cur_generate) {
func = new PFunction(func_name, pform_cur_generate->lexical_scope,
is_auto);
FILE_NAME(func, loc);
// Check if the function is already in the dictionary.
if (pform_cur_generate->funcs.find(func->pscope_name()) !=
pform_cur_generate->funcs.end()) {
@ -331,11 +316,7 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, char*name,
error_count += 1;
}
pform_cur_generate->funcs[func->pscope_name()] = func;
pform_cur_generate->lexical_scope = func;
} else {
func = new PFunction(func_name, lexical_scope,
is_auto);
FILE_NAME(func, loc);
// Check if the function is already in the dictionary.
if (pform_cur_module->funcs.find(func->pscope_name()) !=
pform_cur_module->funcs.end()) {
@ -345,8 +326,8 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, char*name,
error_count += 1;
}
pform_cur_module->funcs[func->pscope_name()] = func;
lexical_scope = func;
}
lexical_scope = func;
return func;
}
@ -355,14 +336,8 @@ PBlock* pform_push_block_scope(char*name, PBlock::BL_TYPE bt)
{
perm_string block_name = lex_strings.make(name);
PBlock*block;
if (pform_cur_generate) {
block = new PBlock(block_name, pform_cur_generate->lexical_scope, bt);
pform_cur_generate->lexical_scope = block;
} else {
block = new PBlock(block_name, lexical_scope, bt);
lexical_scope = block;
}
PBlock*block = new PBlock(block_name, lexical_scope, bt);
lexical_scope = block;
return block;
}
@ -380,29 +355,10 @@ void pform_bind_attributes(map<perm_string,PExpr*>&attributes,
delete attr;
}
static LexicalScope*pform_get_cur_scope()
{
if (pform_cur_generate)
if (pform_cur_generate->lexical_scope)
return pform_cur_generate->lexical_scope;
else
return pform_cur_generate;
else
return lexical_scope;
}
static bool pform_at_module_level()
{
if (pform_cur_generate)
if (pform_cur_generate->lexical_scope)
return false;
else
return true;
else
if (lexical_scope->pscope_parent())
return false;
else
return true;
return (lexical_scope == pform_cur_module)
|| (lexical_scope == pform_cur_generate);
}
PWire*pform_get_wire_in_scope(perm_string name)
@ -411,22 +367,22 @@ PWire*pform_get_wire_in_scope(perm_string name)
scope depth will be empty because generate schemes
cannot be within sub-scopes. Only directly in
modules. */
return pform_get_cur_scope()->wires_find(name);
return lexical_scope->wires_find(name);
}
static void pform_put_wire_in_scope(perm_string name, PWire*net)
{
pform_get_cur_scope()->wires[name] = net;
lexical_scope->wires[name] = net;
}
static void pform_put_behavior_in_scope(PProcess*pp)
{
pform_get_cur_scope()->behaviors.push_back(pp);
lexical_scope->behaviors.push_back(pp);
}
void pform_put_behavior_in_scope(AProcess*pp)
{
pform_get_cur_scope()->analog_behaviors.push_back(pp);
lexical_scope->analog_behaviors.push_back(pp);
}
void pform_set_default_nettype(NetNet::Type type,
@ -819,7 +775,7 @@ void pform_endmodule(const char*name, bool in_celldefine,
// The current lexical scope should be this module by now, and
// this module should not have a parent lexical scope.
ivl_assert(*pform_cur_module, lexical_scope == pform_cur_module);
lexical_scope = pform_cur_module->pscope_parent();
pform_pop_scope();
ivl_assert(*pform_cur_module, lexical_scope == 0);
pform_cur_module = 0;
@ -864,11 +820,11 @@ void pform_start_generate_for(const struct vlltype&li,
PExpr*test,
char*ident2, PExpr*next)
{
PGenerate*gen = new PGenerate(scope_generate_counter++);
PGenerate*gen = new PGenerate(lexical_scope, scope_generate_counter++);
lexical_scope = gen;
FILE_NAME(gen, li);
gen->parent = pform_cur_generate;
pform_cur_generate = gen;
pform_cur_generate->scheme_type = PGenerate::GS_LOOP;
@ -884,11 +840,11 @@ void pform_start_generate_for(const struct vlltype&li,
void pform_start_generate_if(const struct vlltype&li, PExpr*test)
{
PGenerate*gen = new PGenerate(scope_generate_counter++);
PGenerate*gen = new PGenerate(lexical_scope, scope_generate_counter++);
lexical_scope = gen;
FILE_NAME(gen, li);
gen->parent = pform_cur_generate;
pform_cur_generate = gen;
pform_cur_generate->scheme_type = PGenerate::GS_CONDIT;
@ -906,11 +862,11 @@ void pform_start_generate_else(const struct vlltype&li)
PGenerate*cur = pform_cur_generate;
pform_endgenerate();
PGenerate*gen = new PGenerate(scope_generate_counter++);
PGenerate*gen = new PGenerate(lexical_scope, scope_generate_counter++);
lexical_scope = gen;
FILE_NAME(gen, li);
gen->parent = pform_cur_generate;
pform_cur_generate = gen;
pform_cur_generate->scheme_type = PGenerate::GS_ELSE;
@ -926,11 +882,11 @@ void pform_start_generate_else(const struct vlltype&li)
*/
void pform_start_generate_case(const struct vlltype&li, PExpr*expr)
{
PGenerate*gen = new PGenerate(scope_generate_counter++);
PGenerate*gen = new PGenerate(lexical_scope, scope_generate_counter++);
lexical_scope = gen;
FILE_NAME(gen, li);
gen->parent = pform_cur_generate;
pform_cur_generate = gen;
pform_cur_generate->scheme_type = PGenerate::GS_CASE;
@ -945,11 +901,11 @@ void pform_start_generate_case(const struct vlltype&li, PExpr*expr)
*/
void pform_start_generate_nblock(const struct vlltype&li, char*name)
{
PGenerate*gen = new PGenerate(scope_generate_counter++);
PGenerate*gen = new PGenerate(lexical_scope, scope_generate_counter++);
lexical_scope = gen;
FILE_NAME(gen, li);
gen->parent = pform_cur_generate;
pform_cur_generate = gen;
pform_cur_generate->scheme_type = PGenerate::GS_NBLOCK;
@ -973,11 +929,11 @@ void pform_generate_case_item(const struct vlltype&li, svector<PExpr*>*expr_list
assert(pform_cur_generate);
assert(pform_cur_generate->scheme_type == PGenerate::GS_CASE);
PGenerate*gen = new PGenerate(pform_cur_generate->id_number);
PGenerate*gen = new PGenerate(lexical_scope, pform_cur_generate->id_number);
lexical_scope = gen;
FILE_NAME(gen, li);
gen->parent = pform_cur_generate;
pform_cur_generate = gen;
pform_cur_generate->scheme_type = PGenerate::GS_CASE_ITEM;
@ -1017,17 +973,20 @@ void pform_endgenerate()
pform_cur_generate->scope_name = lex_strings.make(tmp);
}
PGenerate*cur = pform_cur_generate;
pform_cur_generate = cur->parent;
// The current lexical scope should be this generate construct by now
ivl_assert(*pform_cur_generate, lexical_scope == pform_cur_generate);
pform_pop_scope();
if (pform_cur_generate != 0) {
assert(cur->scheme_type == PGenerate::GS_CASE_ITEM
|| pform_cur_generate->scheme_type != PGenerate::GS_CASE);
pform_cur_generate->generate_schemes.push_back(cur);
PGenerate*parent_generate = dynamic_cast<PGenerate*>(lexical_scope);
if (parent_generate) {
assert(pform_cur_generate->scheme_type == PGenerate::GS_CASE_ITEM
|| parent_generate->scheme_type != PGenerate::GS_CASE);
parent_generate->generate_schemes.push_back(pform_cur_generate);
} else {
assert(cur->scheme_type != PGenerate::GS_CASE_ITEM);
pform_cur_module->generate_schemes.push_back(cur);
assert(pform_cur_generate->scheme_type != PGenerate::GS_CASE_ITEM);
pform_cur_module->generate_schemes.push_back(pform_cur_generate);
}
pform_cur_generate = parent_generate;
}
MIN_TYP_MAX min_typ_max_flag = TYP;
@ -1478,10 +1437,8 @@ void pform_set_net_range(list<perm_string>*names,
*/
static void pform_make_event(perm_string name, const char*fn, unsigned ln)
{
LexicalScope*scope = pform_get_cur_scope();
// Check if the named event is already in the dictionary.
if (scope->events.find(name) != scope->events.end()) {
if (lexical_scope->events.find(name) != lexical_scope->events.end()) {
LineInfo tloc;
FILE_NAME(&tloc, fn, ln);
cerr << tloc.get_fileline() << ": error: duplicate definition "
@ -1492,7 +1449,7 @@ static void pform_make_event(perm_string name, const char*fn, unsigned ln)
PEvent*event = new PEvent(name);
FILE_NAME(event, fn, ln);
scope->events[name] = event;
lexical_scope->events[name] = event;
}
void pform_make_events(list<perm_string>*names, const char*fn, unsigned ln)
@ -2149,12 +2106,7 @@ void pform_set_type_attrib(perm_string name, const string&key,
*/
void pform_set_reg_idx(perm_string name, PExpr*l, PExpr*r)
{
PWire*cur = 0;
if (pform_cur_generate) {
cur = pform_cur_generate->wires_find(name);
} else {
cur = lexical_scope->wires_find(name);
}
PWire*cur = lexical_scope->wires_find(name);
if (cur == 0) {
VLerror("internal error: name is not a valid memory for index.");
return;
@ -2187,7 +2139,7 @@ void pform_set_parameter(const struct vlltype&loc,
bool signed_flag, svector<PExpr*>*range, PExpr*expr,
LexicalScope::range_t*value_range)
{
LexicalScope*scope = pform_get_cur_scope();
LexicalScope*scope = lexical_scope;
if (scope == pform_cur_generate) {
VLerror("parameter declarations are not permitted in generate blocks");
return;
@ -2239,7 +2191,7 @@ void pform_set_localparam(const struct vlltype&loc,
perm_string name, ivl_variable_type_t type,
bool signed_flag, svector<PExpr*>*range, PExpr*expr)
{
LexicalScope*scope = pform_get_cur_scope();
LexicalScope*scope = lexical_scope;
// Check if the localparam name is already in the dictionary.
if (scope->localparams.find(name) != scope->localparams.end()) {
@ -2260,7 +2212,7 @@ void pform_set_localparam(const struct vlltype&loc,
}
assert(expr);
Module::param_expr_t&parm = pform_get_cur_scope()->localparams[name];
Module::param_expr_t&parm = scope->localparams[name];
FILE_NAME(&parm, loc);
parm.expr = expr;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2009 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2010 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
@ -978,6 +978,7 @@ void PGenerate::dump(ostream&out, unsigned indent) const
{
out << setw(indent) << "" << "generate(" << id_number << ")";
PGenerate*parent = dynamic_cast<PGenerate*>(parent_scope());
switch (scheme_type) {
case GS_NONE:
break;
@ -999,6 +1000,7 @@ void PGenerate::dump(ostream&out, unsigned indent) const
out << " case (" << *loop_test << ")";
break;
case GS_CASE_ITEM:
assert(parent);
if (loop_test)
out << " (" << *loop_test << ") == (" << *parent->loop_test << ")";
else