Added support for default subroutine lifetimes (SystemVerilog).

(cherry picked from commit 6e718c2e0c)
This commit is contained in:
Martin Whitaker 2016-03-19 17:27:27 +00:00
parent 4aef636559
commit 7d2eeb0137
6 changed files with 127 additions and 67 deletions

View File

@ -57,6 +57,9 @@ class LexicalScope {
// A virtual destructor is so that dynamic_cast can work. // A virtual destructor is so that dynamic_cast can work.
virtual ~LexicalScope() { } virtual ~LexicalScope() { }
enum lifetime_t { INHERITED, STATIC, AUTOMATIC };
lifetime_t default_lifetime;
struct range_t { struct range_t {
// True if this is an exclude // True if this is an exclude
bool exclude_flag; bool exclude_flag;

91
parse.y
View File

@ -1,7 +1,7 @@
%{ %{
/* /*
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com) * Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com) * Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
@ -452,6 +452,8 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
PSpecPath* specpath; PSpecPath* specpath;
list<index_component_t> *dimensions; list<index_component_t> *dimensions;
LexicalScope::lifetime_t lifetime;
}; };
%token <text> IDENTIFIER SYSTEM_IDENTIFIER STRING TIME_LITERAL %token <text> IDENTIFIER SYSTEM_IDENTIFIER STRING TIME_LITERAL
@ -560,7 +562,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%type <number> number pos_neg_number %type <number> number pos_neg_number
%type <flag> signing unsigned_signed_opt signed_unsigned_opt %type <flag> signing unsigned_signed_opt signed_unsigned_opt
%type <flag> import_export %type <flag> import_export
%type <flag> K_automatic_opt K_packed_opt K_reg_opt K_static_opt K_virtual_opt %type <flag> K_packed_opt K_reg_opt K_static_opt K_virtual_opt
%type <flag> udp_reg_opt edge_operator %type <flag> udp_reg_opt edge_operator
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1 %type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
%type <letter> udp_input_sym udp_output_sym %type <letter> udp_input_sym udp_output_sym
@ -665,6 +667,8 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%type <int_val> atom2_type %type <int_val> atom2_type
%type <int_val> module_start module_end %type <int_val> module_start module_end
%type <lifetime> lifetime_opt
%token K_TAND %token K_TAND
%right K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ %right K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ
%right K_XOR_EQ K_LS_EQ K_RS_EQ K_RSS_EQ %right K_XOR_EQ K_LS_EQ K_RS_EQ K_RSS_EQ
@ -724,17 +728,17 @@ block_identifier_opt /* */
; ;
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 lifetime_opt class_identifier class_declaration_extends_opt ';'
{ pform_start_class_declaration(@2, $3, $4.type, $4.exprs); } { pform_start_class_declaration(@2, $4, $5.type, $5.exprs, $3); }
class_items_opt K_endclass class_items_opt K_endclass
{ // Process a class. { // Process a class.
pform_end_class_declaration(@8); pform_end_class_declaration(@9);
} }
class_declaration_endlabel_opt class_declaration_endlabel_opt
{ // Wrap up the class. { // Wrap up the class.
if ($10 && $3 && $3->name != $10) { if ($11 && $4 && $4->name != $11) {
yyerror(@10, "error: Class end label doesn't match class name."); yyerror(@11, "error: Class end label doesn't match class name.");
delete[]$10; delete[]$11;
} }
} }
; ;
@ -1194,7 +1198,7 @@ for_step /* IEEE1800-2005: A.6.8 */
definitions in the func_body to take on the scope of the function definitions in the func_body to take on the scope of the function
instead of the module. */ instead of the module. */
function_declaration /* IEEE1800-2005: A.2.6 */ function_declaration /* IEEE1800-2005: A.2.6 */
: K_function K_automatic_opt data_type_or_implicit_or_void IDENTIFIER ';' : K_function lifetime_opt data_type_or_implicit_or_void IDENTIFIER ';'
{ assert(current_function == 0); { assert(current_function == 0);
current_function = pform_push_function_scope(@1, $4, $2); current_function = pform_push_function_scope(@1, $4, $2);
} }
@ -1215,7 +1219,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */
"function name"); "function name");
} }
if (! gn_system_verilog()) { if (! gn_system_verilog()) {
yyerror(@11, "error: Function end label require " yyerror(@11, "error: Function end labels require "
"SystemVerilog."); "SystemVerilog.");
} }
delete[]$11; delete[]$11;
@ -1223,7 +1227,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */
delete[]$4; delete[]$4;
} }
| K_function K_automatic_opt data_type_or_implicit_or_void IDENTIFIER | K_function lifetime_opt data_type_or_implicit_or_void IDENTIFIER
{ assert(current_function == 0); { assert(current_function == 0);
current_function = pform_push_function_scope(@1, $4, $2); current_function = pform_push_function_scope(@1, $4, $2);
} }
@ -1259,7 +1263,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */
/* Detect and recover from some errors. */ /* Detect and recover from some errors. */
| K_function K_automatic_opt data_type_or_implicit_or_void IDENTIFIER error K_endfunction | K_function lifetime_opt data_type_or_implicit_or_void IDENTIFIER error K_endfunction
{ /* */ { /* */
if (current_function) { if (current_function) {
pform_pop_scope(); pform_pop_scope();
@ -1365,6 +1369,12 @@ jump_statement /* IEEE1800-2005: A.6.5 */
} }
; ;
lifetime_opt /* IEEE1800-2005: A.2.1.3 */
: K_automatic { $$ = LexicalScope::AUTOMATIC; }
| K_static { $$ = LexicalScope::STATIC; }
| { $$ = LexicalScope::INHERITED; }
;
/* Loop statements are kinds of statements. */ /* Loop statements are kinds of statements. */
loop_statement /* IEEE1800-2005: A.6.8 */ loop_statement /* IEEE1800-2005: A.6.8 */
@ -1704,20 +1714,20 @@ open_range_list /* IEEE1800-2005 A.2.11 */
; ;
package_declaration /* IEEE1800-2005 A.1.2 */ package_declaration /* IEEE1800-2005 A.1.2 */
: K_package IDENTIFIER ';' : K_package lifetime_opt IDENTIFIER ';'
{ pform_start_package_declaration(@1, $2); { pform_start_package_declaration(@1, $3, $2);
} }
package_item_list_opt package_item_list_opt
K_endpackage endlabel_opt K_endpackage endlabel_opt
{ pform_end_package_declaration(@1); { pform_end_package_declaration(@1);
// If an end label is present make sure it match the package name. // If an end label is present make sure it match the package name.
if ($7) { if ($8) {
if (strcmp($2,$7) != 0) { if (strcmp($3,$8) != 0) {
yyerror(@7, "error: End label doesn't match package name"); yyerror(@8, "error: End label doesn't match package name");
} }
delete[]$7; delete[]$8;
} }
delete[]$2; delete[]$3;
} }
; ;
@ -1896,7 +1906,7 @@ streaming_concatenation /* IEEE1800-2005: A.8.1 */
task_declaration /* IEEE1800-2005: A.2.7 */ task_declaration /* IEEE1800-2005: A.2.7 */
: K_task K_automatic_opt IDENTIFIER ';' : K_task lifetime_opt IDENTIFIER ';'
{ assert(current_task == 0); { assert(current_task == 0);
current_task = pform_push_task_scope(@1, $3, $2); current_task = pform_push_task_scope(@1, $3, $2);
} }
@ -1909,7 +1919,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
pform_pop_scope(); pform_pop_scope();
current_task = 0; current_task = 0;
if ($7 && $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 requires SystemVerilog.");
} }
delete $7; delete $7;
} }
@ -1932,7 +1942,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
delete[]$3; delete[]$3;
} }
| K_task K_automatic_opt IDENTIFIER '(' | K_task lifetime_opt IDENTIFIER '('
{ assert(current_task == 0); { assert(current_task == 0);
current_task = pform_push_task_scope(@1, $3, $2); current_task = pform_push_task_scope(@1, $3, $2);
} }
@ -1966,7 +1976,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
delete[]$3; delete[]$3;
} }
| K_task K_automatic_opt IDENTIFIER '(' ')' ';' | K_task lifetime_opt IDENTIFIER '(' ')' ';'
{ assert(current_task == 0); { assert(current_task == 0);
current_task = pform_push_task_scope(@1, $3, $2); current_task = pform_push_task_scope(@1, $3, $2);
} }
@ -1983,7 +1993,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
pform_pop_scope(); pform_pop_scope();
current_task = 0; current_task = 0;
if ($9->size() > 1 && !gn_system_verilog()) { if ($9->size() > 1 && !gn_system_verilog()) {
yyerror(@9, "error: Task body with multiple statements requres SystemVerilog."); yyerror(@9, "error: Task body with multiple statements requires SystemVerilog.");
} }
delete $9; delete $9;
} }
@ -2006,7 +2016,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
delete[]$3; delete[]$3;
} }
| K_task K_automatic_opt IDENTIFIER error K_endtask | K_task lifetime_opt IDENTIFIER error K_endtask
{ {
assert(current_task == 0); assert(current_task == 0);
} }
@ -4377,13 +4387,13 @@ local_timeunit_prec_decl2
items, and finally an end marker. */ items, and finally an end marker. */
module module
: attribute_list_opt module_start IDENTIFIER : attribute_list_opt module_start lifetime_opt IDENTIFIER
{ pform_startmodule(@2, $3, $2==K_program, $2==K_interface, $1); } { pform_startmodule(@2, $4, $2==K_program, $2==K_interface, $3, $1); }
module_package_import_list_opt module_package_import_list_opt
module_parameter_port_list_opt module_parameter_port_list_opt
module_port_list_opt module_port_list_opt
module_attribute_foreign ';' module_attribute_foreign ';'
{ pform_module_set_ports($7); } { pform_module_set_ports($8); }
local_timeunit_prec_decl_opt local_timeunit_prec_decl_opt
{ have_timeunit_decl = true; // Every thing past here is { have_timeunit_decl = true; // Every thing past here is
have_timeprec_decl = true; // a check! have_timeprec_decl = true; // a check!
@ -4409,22 +4419,22 @@ module
} }
// Check that program/endprogram and module/endmodule // Check that program/endprogram and module/endmodule
// keywords match. // keywords match.
if ($2 != $14) { if ($2 != $15) {
switch ($2) { switch ($2) {
case K_module: case K_module:
yyerror(@14, "error: module not closed by endmodule."); yyerror(@15, "error: module not closed by endmodule.");
break; break;
case K_program: case K_program:
yyerror(@14, "error: program not closed by endprogram."); yyerror(@15, "error: program not closed by endprogram.");
break; break;
case K_interface: case K_interface:
yyerror(@14, "error: interface not closed by endinterface."); yyerror(@15, "error: interface not closed by endinterface.");
break; break;
default: default:
break; break;
} }
} }
pform_endmodule($3, in_celldefine, ucd); pform_endmodule($4, in_celldefine, ucd);
have_timeunit_decl = false; // We will allow decls again. have_timeunit_decl = false; // We will allow decls again.
have_timeprec_decl = false; have_timeprec_decl = false;
} }
@ -4434,19 +4444,19 @@ module
// endlabel_opt but still have the pform_endmodule() called // endlabel_opt but still have the pform_endmodule() called
// early enough that the lexor can know we are outside the // early enough that the lexor can know we are outside the
// module. // module.
if ($16) { if ($17) {
if (strcmp($3,$16) != 0) { if (strcmp($4,$17) != 0) {
switch ($2) { switch ($2) {
case K_module: case K_module:
yyerror(@16, "error: End label doesn't match " yyerror(@17, "error: End label doesn't match "
"module name."); "module name.");
break; break;
case K_program: case K_program:
yyerror(@16, "error: End label doesn't match " yyerror(@17, "error: End label doesn't match "
"program name."); "program name.");
break; break;
case K_interface: case K_interface:
yyerror(@16, "error: End label doesn't match " yyerror(@17, "error: End label doesn't match "
"interface name."); "interface name.");
break; break;
default: default:
@ -4457,9 +4467,9 @@ module
yyerror(@8, "error: Module end labels require " yyerror(@8, "error: Module end labels require "
"SystemVerilog."); "SystemVerilog.");
} }
delete[]$16; delete[]$17;
} }
delete[]$3; delete[]$4;
} }
; ;
@ -6782,7 +6792,6 @@ udp_primitive
presence is significant. This is a fairly common pattern so presence is significant. This is a fairly common pattern so
collect those rules here. */ collect those rules here. */
K_automatic_opt: K_automatic { $$ = true; } | { $$ = false; } ;
K_packed_opt : K_packed { $$ = true; } | { $$ = false; } ; K_packed_opt : K_packed { $$ = true; } | { $$ = false; } ;
K_reg_opt : K_reg { $$ = true; } | { $$ = false; } ; K_reg_opt : K_reg { $$ = true; } | { $$ = false; } ;
K_static_opt : K_static { $$ = true; } | { $$ = false; } ; K_static_opt : K_static { $$ = true; } | { $$ = false; } ;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com) * Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
@ -312,12 +312,29 @@ static inline void FILE_NAME(LineInfo*obj, const char*file, unsigned lineno)
*/ */
static LexicalScope* lexical_scope = 0; static LexicalScope* lexical_scope = 0;
LexicalScope* pform_peek_scope(void)
{
assert(lexical_scope);
return lexical_scope;
}
void pform_pop_scope() void pform_pop_scope()
{ {
assert(lexical_scope); assert(lexical_scope);
lexical_scope = lexical_scope->parent_scope(); lexical_scope = lexical_scope->parent_scope();
} }
static LexicalScope::lifetime_t find_lifetime(LexicalScope::lifetime_t lifetime)
{
if (lifetime != LexicalScope::INHERITED)
return lifetime;
if (lexical_scope != 0)
return lexical_scope->default_lifetime;
return LexicalScope::STATIC;
}
static PScopeExtra* find_nearest_scopex(LexicalScope*scope) static PScopeExtra* find_nearest_scopex(LexicalScope*scope)
{ {
PScopeExtra*scopex = dynamic_cast<PScopeExtra*> (scope); PScopeExtra*scopex = dynamic_cast<PScopeExtra*> (scope);
@ -328,15 +345,11 @@ static PScopeExtra* find_nearest_scopex(LexicalScope*scope)
return scopex; return scopex;
} }
LexicalScope* pform_peek_scope(void) PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name,
{ LexicalScope::lifetime_t lifetime)
assert(lexical_scope);
return lexical_scope;
}
PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name)
{ {
PClass*class_scope = new PClass(name, lexical_scope); PClass*class_scope = new PClass(name, lexical_scope);
class_scope->default_lifetime = find_lifetime(lifetime);
FILE_NAME(class_scope, loc); FILE_NAME(class_scope, loc);
PScopeExtra*scopex = find_nearest_scopex(lexical_scope); PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
@ -364,20 +377,27 @@ PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name)
return class_scope; return class_scope;
} }
PPackage* pform_push_package_scope(const struct vlltype&loc, perm_string name) PPackage* pform_push_package_scope(const struct vlltype&loc, perm_string name,
LexicalScope::lifetime_t lifetime)
{ {
PPackage*pkg_scope = new PPackage(name, lexical_scope); PPackage*pkg_scope = new PPackage(name, lexical_scope);
pkg_scope->default_lifetime = find_lifetime(lifetime);
FILE_NAME(pkg_scope, loc); FILE_NAME(pkg_scope, loc);
lexical_scope = pkg_scope; lexical_scope = pkg_scope;
return pkg_scope; return pkg_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,
LexicalScope::lifetime_t lifetime)
{ {
perm_string task_name = lex_strings.make(name); perm_string task_name = lex_strings.make(name);
LexicalScope::lifetime_t default_lifetime = find_lifetime(lifetime);
bool is_auto = default_lifetime == LexicalScope::AUTOMATIC;
PTask*task = new PTask(task_name, lexical_scope, is_auto); PTask*task = new PTask(task_name, lexical_scope, is_auto);
task->default_lifetime = default_lifetime;
FILE_NAME(task, loc); FILE_NAME(task, loc);
PScopeExtra*scopex = find_nearest_scopex(lexical_scope); PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
@ -424,11 +444,15 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto)
} }
PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name, PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name,
bool is_auto) LexicalScope::lifetime_t lifetime)
{ {
perm_string func_name = lex_strings.make(name); perm_string func_name = lex_strings.make(name);
LexicalScope::lifetime_t default_lifetime = find_lifetime(lifetime);
bool is_auto = default_lifetime == LexicalScope::AUTOMATIC;
PFunction*func = new PFunction(func_name, lexical_scope, is_auto); PFunction*func = new PFunction(func_name, lexical_scope, is_auto);
func->default_lifetime = default_lifetime;
FILE_NAME(func, loc); FILE_NAME(func, loc);
PScopeExtra*scopex = find_nearest_scopex(lexical_scope); PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
@ -1131,6 +1155,7 @@ verinum* pform_verinum_with_size(verinum*siz, verinum*val,
void pform_startmodule(const struct vlltype&loc, const char*name, void pform_startmodule(const struct vlltype&loc, const char*name,
bool program_block, bool is_interface, bool program_block, bool is_interface,
LexicalScope::lifetime_t lifetime,
list<named_pexpr_t>*attr) list<named_pexpr_t>*attr)
{ {
if (! pform_cur_module.empty() && !gn_system_verilog()) { if (! pform_cur_module.empty() && !gn_system_verilog()) {
@ -1139,6 +1164,12 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
error_count += 1; error_count += 1;
} }
if (lifetime != LexicalScope::INHERITED && !gn_system_verilog()) {
cerr << loc << ": error: Default subroutine lifetimes "
"require SystemVerilog." << endl;
error_count += 1;
}
if (gn_system_verilog() && ! pform_cur_module.empty()) { if (gn_system_verilog() && ! pform_cur_module.empty()) {
if (pform_cur_module.front()->program_block) { if (pform_cur_module.front()->program_block) {
cerr << loc << ": error: module, program, or interface " cerr << loc << ": error: module, program, or interface "
@ -1158,6 +1189,8 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
Module*cur_module = new Module(lexical_scope, lex_name); Module*cur_module = new Module(lexical_scope, lex_name);
cur_module->program_block = program_block; cur_module->program_block = program_block;
cur_module->is_interface = is_interface; cur_module->is_interface = is_interface;
cur_module->default_lifetime = find_lifetime(lifetime);
/* Set the local time unit/precision to the global value. */ /* Set the local time unit/precision to the global value. */
cur_module->time_unit = pform_time_unit; cur_module->time_unit = pform_time_unit;
cur_module->time_precision = pform_time_prec; cur_module->time_precision = pform_time_prec;

24
pform.h
View File

@ -1,7 +1,7 @@
#ifndef IVL_pform_H #ifndef IVL_pform_H
#define IVL_pform_H #define IVL_pform_H
/* /*
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com) * Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -163,6 +163,7 @@ extern PWire* pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_ty
*/ */
extern void pform_startmodule(const struct vlltype&loc, const char*name, extern void pform_startmodule(const struct vlltype&loc, const char*name,
bool program_block, bool is_interface, bool program_block, bool is_interface,
LexicalScope::lifetime_t lifetime,
list<named_pexpr_t>*attr); list<named_pexpr_t>*attr);
extern void pform_check_timeunit_prec(); extern void pform_check_timeunit_prec();
extern void pform_module_set_ports(vector<Module::port_t*>*); extern void pform_module_set_ports(vector<Module::port_t*>*);
@ -186,7 +187,8 @@ extern void pform_endmodule(const char*, bool inside_celldefine,
extern void pform_start_class_declaration(const struct vlltype&loc, extern void pform_start_class_declaration(const struct vlltype&loc,
class_type_t*type, class_type_t*type,
data_type_t*base_type, data_type_t*base_type,
std::list<PExpr*>*base_exprs); std::list<PExpr*>*base_exprs,
LexicalScope::lifetime_t lifetime);
extern void pform_class_property(const struct vlltype&loc, extern void pform_class_property(const struct vlltype&loc,
property_qualifier_t pq, property_qualifier_t pq,
data_type_t*data_type, data_type_t*data_type,
@ -211,7 +213,8 @@ extern void pform_make_udp(perm_string name,
* Package related functions. * Package related functions.
*/ */
extern void pform_start_package_declaration(const struct vlltype&loc, extern void pform_start_package_declaration(const struct vlltype&loc,
const char*type); const char*type,
LexicalScope::lifetime_t lifetime);
extern void pform_end_package_declaration(const struct vlltype&loc); extern void pform_end_package_declaration(const struct vlltype&loc);
extern void pform_package_import(const struct vlltype&loc, extern void pform_package_import(const struct vlltype&loc,
PPackage*pkg, const char*ident); PPackage*pkg, const char*ident);
@ -246,13 +249,20 @@ extern void pform_pop_scope();
*/ */
extern LexicalScope* pform_peek_scope(); extern LexicalScope* pform_peek_scope();
extern PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name); extern PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name,
LexicalScope::lifetime_t lifetime);
extern PFunction*pform_push_constructor_scope(const struct vlltype&loc); extern PFunction*pform_push_constructor_scope(const struct vlltype&loc);
extern PPackage* pform_push_package_scope(const struct vlltype&loc, perm_string name);
extern PPackage* pform_push_package_scope(const struct vlltype&loc, perm_string name,
LexicalScope::lifetime_t lifetime);
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); LexicalScope::lifetime_t lifetime);
extern PFunction*pform_push_function_scope(const struct vlltype&loc, const char*name, extern PFunction*pform_push_function_scope(const struct vlltype&loc, const char*name,
bool is_auto); LexicalScope::lifetime_t lifetime);
extern PBlock*pform_push_block_scope(char*name, PBlock::BL_TYPE tt); extern PBlock*pform_push_block_scope(char*name, PBlock::BL_TYPE tt);
extern void pform_put_behavior_in_scope(AProcess*proc); extern void pform_put_behavior_in_scope(AProcess*proc);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012 Stephen Williams (steve@icarus.com) * Copyright (c) 2012-2016 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
@ -35,12 +35,13 @@ map<perm_string,PPackage*> pform_packages;
static PPackage*pform_cur_package = 0; static PPackage*pform_cur_package = 0;
void pform_start_package_declaration(const struct vlltype&loc, const char*name) void pform_start_package_declaration(const struct vlltype&loc, const char*name,
LexicalScope::lifetime_t lifetime)
{ {
ivl_assert(loc, pform_cur_package == 0); ivl_assert(loc, pform_cur_package == 0);
perm_string use_name = lex_strings.make(name); perm_string use_name = lex_strings.make(name);
PPackage*pkg_scope = pform_push_package_scope(loc, use_name); PPackage*pkg_scope = pform_push_package_scope(loc, use_name, lifetime);
FILE_NAME(pkg_scope, loc); FILE_NAME(pkg_scope, loc);
pform_cur_package = pkg_scope; pform_cur_package = pkg_scope;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com) * Copyright (c) 2012-2016 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -36,9 +36,13 @@ static PClass*pform_cur_class = 0;
* if present, are the "exprs" that would be passed to a chained * if present, are the "exprs" that would be passed to a chained
* constructor. * constructor.
*/ */
void pform_start_class_declaration(const struct vlltype&loc, class_type_t*type, data_type_t*base_type, list<PExpr*>*base_exprs) void pform_start_class_declaration(const struct vlltype&loc,
class_type_t*type,
data_type_t*base_type,
list<PExpr*>*base_exprs,
LexicalScope::lifetime_t lifetime)
{ {
PClass*class_scope = pform_push_class_scope(loc, type->name); PClass*class_scope = pform_push_class_scope(loc, type->name, lifetime);
class_scope->type = type; class_scope->type = type;
assert(pform_cur_class == 0); assert(pform_cur_class == 0);
pform_cur_class = class_scope; pform_cur_class = class_scope;
@ -127,7 +131,7 @@ void pform_set_constructor_return(PFunction*net)
PFunction*pform_push_constructor_scope(const struct vlltype&loc) PFunction*pform_push_constructor_scope(const struct vlltype&loc)
{ {
assert(pform_cur_class); assert(pform_cur_class);
PFunction*func = pform_push_function_scope(loc, "new", true); PFunction*func = pform_push_function_scope(loc, "new", LexicalScope::AUTOMATIC);
return func; return func;
} }
@ -138,7 +142,7 @@ void pform_end_class_declaration(const struct vlltype&loc)
// If there were initializer statements, then collect them // If there were initializer statements, then collect them
// into an implicit constructor function. // into an implicit constructor function.
if (! pform_cur_class->type->initialize.empty()) { if (! pform_cur_class->type->initialize.empty()) {
PFunction*func = pform_push_function_scope(loc, "new@", true); PFunction*func = pform_push_function_scope(loc, "new@", LexicalScope::AUTOMATIC);
func->set_ports(0); func->set_ports(0);
pform_set_constructor_return(func); pform_set_constructor_return(func);
pform_set_this_class(loc, func); pform_set_this_class(loc, func);