diff --git a/elab_expr.cc b/elab_expr.cc index e28b6ede8..bc6bc65b1 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -2601,7 +2601,7 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope, /* Add the implicit this reference when requested. */ if (add_this_flag) { assert(use_path.empty()); - use_path.push_front(name_component_t(perm_string::literal("@"))); + use_path.push_front(name_component_t(perm_string::literal(THIS_TOKEN))); } // If there is no object to the left of the method name, then @@ -3906,7 +3906,7 @@ NetExpr* PEIdent::elaborate_expr_class_member_(Design*des, NetScope*scope, NetScope*scope_method = find_method_containing_scope(*this, scope); ivl_assert(*this, scope_method); - NetNet*this_net = scope_method->find_signal(perm_string::literal("@")); + NetNet*this_net = scope_method->find_signal(perm_string::literal(THIS_TOKEN)); if (this_net == 0) { cerr << get_fileline() << ": internal error: " << "Unable to find 'this' port of " << scope_path(scope_method) @@ -5766,7 +5766,7 @@ NetExpr* PENewClass::elaborate_expr_constructor_(Design*des, NetScope*scope, // The return value of the initializer is the "this" // variable, instead of the "new&" scope name. - NetNet*res1 = new1_scope->find_signal(perm_string::literal("@")); + NetNet*res1 = new1_scope->find_signal(perm_string::literal(THIS_TOKEN)); ivl_assert(*this, res1); NetESignal*eres = new NetESignal(res1); @@ -5853,7 +5853,7 @@ NetExpr* PENewClass::elaborate_expr_constructor_(Design*des, NetScope*scope, // The return value for the constructor is actually the "this" // variable, instead of the "new" scope name. - NetNet*res = new_scope->find_signal(perm_string::literal("@")); + NetNet*res = new_scope->find_signal(perm_string::literal(THIS_TOKEN)); ivl_assert(*this, res); NetESignal*eres = new NetESignal(res); diff --git a/elab_lval.cc b/elab_lval.cc index 14f0aa227..441b1d72f 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -378,7 +378,7 @@ NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des, NetScope*scope_method = find_method_containing_scope(*this, scope); ivl_assert(*this, scope_method); - NetNet*this_net = scope_method->find_signal(perm_string::literal("@")); + NetNet*this_net = scope_method->find_signal(perm_string::literal(THIS_TOKEN)); if (this_net == 0) { cerr << get_fileline() << ": internal error: " << "Unable to find 'this' port of " << scope_path(scope_method) diff --git a/elab_sig.cc b/elab_sig.cc index fb772ce04..e1b472db2 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -578,10 +578,10 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const // source code for the definition may be: // function new(...); // endfunction - // In this case, the "@" port is the synthetic "this" - // argument and we also use it as a return value at the - // same time. - ret_sig = scope->find_signal(perm_string::literal("@")); + // In this case, the "@" port (THIS_TOKEN) is the synthetic + // "this" argument and we also use it as a return value at + // the same time. + ret_sig = scope->find_signal(perm_string::literal(THIS_TOKEN)); ivl_assert(*this, ret_sig); if (debug_elaborate) diff --git a/elaborate.cc b/elaborate.cc index ae3345cde..e6c9b6e3c 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -3002,6 +3002,25 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const for (unsigned idx = 0 ; idx < list_.size() ; idx += 1) { assert(list_[idx]); + + // Detect the error that a super.new() statement is in the + // midst of a block. Report the error. Continue on with the + // elaboration so that other errors might be found. + if (PChainConstructor*supernew = dynamic_cast (list_[idx])) { + if (debug_elaborate) { + cerr << get_fileline() << ": PBlock::elaborate: " + << "Found super.new statement, idx=" << idx << ", " + << " at " << supernew->get_fileline() << "." + << endl; + } + if (idx > 0) { + des->errors += 1; + cerr << supernew->get_fileline() << ": error: " + << "super.new(...) must be the first statement in a block." + << endl; + } + } + NetProc*tmp = list_[idx]->elaborate(des, nscope); // If the statement fails to elaborate, then simply // ignore it. Presumably, the elaborate for the @@ -3266,7 +3285,7 @@ NetProc* PChainConstructor::elaborate(Design*des, NetScope*scope) const // Need the "this" variable for the current constructor. We're // going to pass this to the chained constructor. - NetNet*var_this = scope->find_signal(perm_string::literal("@")); + NetNet*var_this = scope->find_signal(perm_string::literal(THIS_TOKEN)); // If super.new is an implicit constructor, then there are no // arguments (other than "this" to worry about, so make a @@ -3728,7 +3747,7 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope, /* Add the implicit this reference when requested. */ if (add_this_flag) { assert(use_path.empty()); - use_path.push_front(name_component_t(perm_string::literal("@"))); + use_path.push_front(name_component_t(perm_string::literal(THIS_TOKEN))); } // There is no signal to search for so this cannot be a method. diff --git a/parse.y b/parse.y index ee138354c..ea855fe09 100644 --- a/parse.y +++ b/parse.y @@ -68,7 +68,7 @@ static LexicalScope::lifetime_t var_lifetime; static pform_name_t* pform_create_this(void) { - name_component_t name (perm_string::literal("@")); + name_component_t name (perm_string::literal(THIS_TOKEN)); pform_name_t*res = new pform_name_t; res->push_back(name); return res; @@ -76,7 +76,7 @@ static pform_name_t* pform_create_this(void) static pform_name_t* pform_create_super(void) { - name_component_t name (perm_string::literal("#")); + name_component_t name (perm_string::literal(SUPER_TOKEN)); pform_name_t*res = new pform_name_t; res->push_back(name); return res; @@ -6897,6 +6897,9 @@ statement_item /* This is roughly statement_item in the LRM */ | implicit_class_handle '.' K_new '(' expression_list_with_nuls ')' ';' { PChainConstructor*tmp = new PChainConstructor(*$5); FILE_NAME(tmp, @3); + if (peek_head_name(*$1) == THIS_TOKEN) { + yyerror(@1, "error: this.new is invalid syntax. Did you mean super.new?"); + } delete $1; $$ = tmp; } diff --git a/pform_pclass.cc b/pform_pclass.cc index c294f6000..9e131b85c 100644 --- a/pform_pclass.cc +++ b/pform_pclass.cc @@ -109,7 +109,7 @@ void pform_set_this_class(const struct vlltype&loc, PTaskFunc*net) return; list*this_name = new list; - this_name->push_back(perm_string::literal("@")); + this_name->push_back(perm_string::literal(THIS_TOKEN)); vector*this_port = pform_make_task_ports(loc, NetNet::PINPUT, pform_cur_class->type, diff --git a/pform_types.h b/pform_types.h index e961369b9..d78847d55 100644 --- a/pform_types.h +++ b/pform_types.h @@ -381,6 +381,14 @@ inline perm_string peek_tail_name(const pform_name_t&that) return that.back().name; } +/* + * In pform names, the "super" and "this" keywords are converted to + * These tokens so that they don't interfere with the namespace and + * are handled specially. + */ +# define SUPER_TOKEN "#" +# define THIS_TOKEN "@" + extern std::ostream& operator<< (std::ostream&out, const pform_name_t&); extern std::ostream& operator<< (std::ostream&out, const name_component_t&that); extern std::ostream& operator<< (std::ostream&out, const index_component_t&that);