# HG changeset patch # User jwe # Date 859418952 0 # Node ID 52e7c4509983b77e3a5cfa49f79525313155c814 # Parent b11fb5e85dc52d84eda7849e8b0e7d0bc0d0253f [project @ 1997-03-26 23:27:35 by jwe] diff --git a/src/ChangeLog b/src/ChangeLog --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,40 @@ +Wed Mar 26 17:08:27 1997 John W. Eaton + + Implement static variable declaration: + + * lex.l (is_keyword): Handle static. + * octave.gperf: Likewise. + * parse.y (Vwarn_comma_in_declaration): Rename from + Vwarn_comma_in_global_decl. + Handle new static command. + * pt-cmd.h, pt-cmd.cc (class tree_decl_command): New base class + for static and global declaration commands. + (class tree_global_command): Derive from tree_decl_command. + (class tree_static_command): New class, derived from tree_decl_command. + * pt-fvc.cc, pt-fvc.h (tree_identifier::mark_as_static): New function. + * pt-misc.h, pt-misc.h (class tree_decl_elt): Rename from tree_global. + (class tree_decl_init_list): Rename from tree_global_init_list. + * pt-pr-code.cc, pt-pr-code.h (tree_print_code::visit_decl_command): + Rename from visit_global_command. + (tree_print_code::visit_decl_elt): Rename from visit_global. + (tree_print_code::visit_decl_init_list): Rename from + visit_global_init_list. + * pt-walk.h (tree_walker::visit_decl_command): Rename from + visit_global_command. + (tree_walker::visit_decl_elt): Rename from visit_tree_global. + (tree_walker::visit_decl_init_list): Rename from + visit_global_init_list. + * variables.cc (link_to_global_variable): Trying to make a static + variable global is an error. + * SLList-misc.cc: Instantiate lists of pointers to tree_decl_elt + objects, not tree_global objects. + * symtab.h, symtab.cc (symbol_record::tagged_static): New field. + (symbol_record::mark_as_static, symbol_record::is_static): + New functions. + * symtab.cc (symbol_record::init_state): Initialize tagged_static. + (symbol_record::clear): Don't clear static variables. + * symtab.cc (push_context): Don't do anything for static variables. + Tue Mar 25 17:17:17 1997 John W. Eaton * ov-bool-mat.cc (octave_bool_matrix::is_true): Write guts. diff --git a/src/SLList-misc.cc b/src/SLList-misc.cc --- a/src/SLList-misc.cc +++ b/src/SLList-misc.cc @@ -42,8 +42,8 @@ template class SLList; template class SLNode; -template class SLList; -template class SLNode; +template class SLList; +template class SLNode; /* ;;; Local Variables: *** diff --git a/src/lex.l b/src/lex.l --- a/src/lex.l +++ b/src/lex.l @@ -967,6 +967,7 @@ case global_kw: case otherwise_kw: case return_kw: + case static_kw: case unwind_protect_cleanup_kw: break; diff --git a/src/octave.gperf b/src/octave.gperf --- a/src/octave.gperf +++ b/src/octave.gperf @@ -26,6 +26,7 @@ otherwise_kw, replot_kw, return_kw, + static_kw, switch_kw, try_kw, unwind_protect_kw, @@ -60,6 +61,7 @@ otherwise, OTHERWISE, otherwise_kw replot, PLOT, replot_kw return, FUNC_RET, return_kw +static, STATIC, static_kw switch, SWITCH, switch_kw try, TRY, try_kw unwind_protect, UNWIND, unwind_protect_kw diff --git a/src/parse.y b/src/parse.y --- a/src/parse.y +++ b/src/parse.y @@ -79,7 +79,7 @@ // // octave> global a, b = 2 // -static bool Vwarn_comma_in_global_decl; +static bool Vwarn_comma_in_declaration; // If TRUE, generate warning if declared function name disagrees with // the name of the file in which it is defined. @@ -239,12 +239,19 @@ static tree_index_expression *make_index_expression (tree_indirect_ref *indir, tree_argument_list *args); +// Make a declaration command. +static tree_decl_command *make_decl_command + (int tok, token *tok_val, tree_decl_init_list *lst); + // Finish building a matrix list. static tree_expression *finish_matrix (tree_matrix *m); // Maybe print a warning. Duh. static void maybe_warn_missing_semi (tree_statement_list *); +// Maybe print a warning. Duh. +static void maybe_warn_comma_in_decl (void); + // Set the print flag for a statement based on the separator type. static void set_stmt_print_flag (tree_statement_list *, char, bool); @@ -290,9 +297,9 @@ tree_switch_command *tree_switch_command_type; tree_switch_case *tree_switch_case_type; tree_switch_case_list *tree_switch_case_list_type; - tree_global *tree_global_type; - tree_global_init_list *tree_global_init_list_type; - tree_global_command *tree_global_command_type; + tree_decl_elt *tree_decl_elt_type; + tree_decl_init_list *tree_decl_init_list_type; + tree_decl_command *tree_decl_command_type; tree_statement *tree_statement_type; tree_statement_list *tree_statement_list_type; tree_plot_command *tree_plot_command_type; @@ -323,7 +330,7 @@ %token BREAK CONTINUE FUNC_RET %token UNWIND CLEANUP %token TRY CATCH -%token GLOBAL +%token GLOBAL STATIC %token TEXT_ID // Other tokens. @@ -356,9 +363,9 @@ %type switch_command %type switch_case default_case %type case_list1 case_list -%type global_decl2 -%type global_decl1 -%type global_decl +%type decl2 +%type decl1 +%type declaration %type statement %type simple_list simple_list1 list list1 %type opt_list input1 @@ -600,46 +607,43 @@ { $$ = maybe_convert_to_ans_assign ($1); } ; -global_decl : GLOBAL global_decl1 +decl1 : decl2 + { $$ = new tree_decl_init_list ($1); } + | decl1 decl2 { - $$ = new tree_global_command ($2, $1->line (), - $1->column ()); + $1->append ($2); + $$ = $1; } - ; - -global_decl1 : global_decl2 - { $$ = new tree_global_init_list ($1); } - | global_decl1 optcomma global_decl2 + | decl1 ',' decl2 { + maybe_warn_comma_in_decl (); $1->append ($3); $$ = $1; } - -global_decl2 : identifier - { $$ = new tree_global ($1); } + ; + +decl2 : identifier + { $$ = new tree_decl_elt ($1); } | identifier '=' expression { tree_simple_assignment_expression *tmp_ass; tmp_ass = new tree_simple_assignment_expression ($1, $3, 0, 0, $2->line (), $2->column ()); - $$ = new tree_global (tmp_ass); + $$ = new tree_decl_elt (tmp_ass); } ; -optcomma : // empty - | ',' - { - if (Vwarn_comma_in_global_decl) - warning ("comma in global declaration not\ - interpreted as a command separator"); - } +declaration : GLOBAL decl1 + { $$ = make_decl_command (GLOBAL, $1, $2); } + | STATIC decl1 + { $$ = make_decl_command (STATIC, $1, $2); } ; command : plot_command { $$ = $1; } | func_def { $$ = $1; } - | global_decl + | declaration { $$ = $1; } | switch_command { $$ = $1; } @@ -2246,6 +2250,8 @@ return fcn->define_ret_list (ret_list); } +// Make an index expression. + static tree_index_expression * make_index_expression (tree_indirect_ref *indir, tree_argument_list *args) { @@ -2266,6 +2272,43 @@ return retval; } +// Make a declaration command. + +static tree_decl_command * +make_decl_command (int tok, token *tok_val, tree_decl_init_list *lst) +{ + tree_decl_command *retval = 0; + + int l = tok_val->line (); + int c = tok_val->column (); + + switch (tok) + { + case GLOBAL: + retval = new tree_global_command (lst, l, c); + break; + + case STATIC: + if (lexer_flags.defining_func) + retval = new tree_static_command (lst, l, c); + else + { + if (reading_script_file) + warning ("ignoring static declaration near line %d of file `%s'", + l, curr_fcn_file_full_name.c_str ()); + else + warning ("ignoring static declaration near line %d", l); + } + break; + + default: + panic_impossible (); + break; + } + + return retval; +} + // Finish building a matrix list. static tree_expression * @@ -2350,6 +2393,19 @@ } } +static void +maybe_warn_comma_in_decl (void) +{ + if (Vwarn_comma_in_declaration)\ + { + warning ("comma in declaration not interpreted as a command separator"); + + if (reading_fcn_file || reading_script_file) + warning ("near line %d of file `%s'", input_line_number, + curr_fcn_file_full_name.c_str ()); + } +} + static int warn_assign_as_truth_value (void) { @@ -2360,9 +2416,9 @@ } static int -warn_comma_in_global_decl (void) +warn_comma_in_declaration (void) { - Vwarn_comma_in_global_decl = check_preference ("warn_comma_in_global_decl"); + Vwarn_comma_in_declaration = check_preference ("warn_comma_in_declaration"); return 0; } @@ -2398,8 +2454,8 @@ DEFVAR (warn_assign_as_truth_value, 1.0, 0, warn_assign_as_truth_value, "produce warning for assignments used as truth values"); - DEFVAR (warn_comma_in_global_decl, 1.0, 0, warn_comma_in_global_decl, - "produce warning for commas in global declarations"); + DEFVAR (warn_comma_in_declaration, 1.0, 0, warn_comma_in_declaration, + "produce warning for commas in declaration statements"); DEFVAR (warn_function_name_clash, 1.0, 0, warn_function_name_clash, "produce warning if function name conflicts with file name"); diff --git a/src/pt-cmd.cc b/src/pt-cmd.cc --- a/src/pt-cmd.cc +++ b/src/pt-cmd.cc @@ -71,28 +71,107 @@ return quit; } +// Base class for declaration commands (global, static). + +tree_decl_command::~tree_decl_command (void) +{ + delete init_list; +} + +void +tree_decl_command::accept (tree_walker& tw) +{ + tw.visit_decl_command (*this); +} + // Global. -tree_global_command::~tree_global_command (void) +static void +do_global_init (tree_decl_elt& elt, bool skip_initializer) { - delete init_list; + tree_identifier *id = elt.ident (); + + if (id) + id->link_to_global (); + else + { + tree_simple_assignment_expression *expr = elt.assign_expr (); + + if (expr) + { + if (expr->left_hand_side_is_identifier_only () + && (id = expr->left_hand_side_id ())) + { + id->link_to_global (); + + if (! (skip_initializer || error_state)) + expr->eval (false); + } + else + error ("global: unable to make structure elements global"); + } + } } void tree_global_command::eval (void) { if (init_list) - init_list->eval (); + { + init_list->eval (do_global_init, initialized); + + initialized = true; + } if (error_state > 0) ::error ("evaluating global command near line %d, column %d", line (), column ()); } +// Static. + +static void +do_static_init (tree_decl_elt& elt, bool) +{ + tree_identifier *id = elt.ident (); + + if (id) + id->mark_as_static (); + else + { + tree_simple_assignment_expression *expr = elt.assign_expr (); + + if (expr) + { + if (expr->left_hand_side_is_identifier_only () + && (id = expr->left_hand_side_id ())) + { + id->mark_as_static (); + + if (! error_state) + expr->eval (false); + } + else + error ("global: unable to make structure elements global"); + } + } +} + void -tree_global_command::accept (tree_walker& tw) +tree_static_command::eval (void) { - tw.visit_global_command (*this); + // Static variables only need to be marked and initialized once. + + if (init_list && ! initialized) + { + init_list->eval (do_static_init, initialized); + + initialized = true; + + if (error_state > 0) + ::error ("evaluating static command near line %d, column %d", + line (), column ()); + } } // While. diff --git a/src/pt-cmd.h b/src/pt-cmd.h --- a/src/pt-cmd.h +++ b/src/pt-cmd.h @@ -32,7 +32,7 @@ class octave_value_list; class tree_statement_list; -class tree_global_init_list; +class tree_decl_init_list; class tree_if_command_list; class tree_switch_case_list; class tree_expression; @@ -43,7 +43,9 @@ class symbol_record; class tree_command; +class tree_decl_command; class tree_global_command; +class tree_static_command; class tree_while_command; class tree_for_command; class tree_if_command; @@ -75,30 +77,74 @@ virtual void eval (void) = 0; }; +// Base class for declaration commands -- global, static, etc. + class -tree_global_command : public tree_command +tree_decl_command : public tree_command +{ +public: + + tree_decl_command (const string& n, int l = -1, int c = -1) + : tree_command (l, c), cmd_name (n), initialized (false), init_list (0) { } + + tree_decl_command (const string& n, tree_decl_init_list *t, + int l = -1, int c = -1) + : tree_command (l, c), cmd_name (n), initialized (false), init_list (t) { } + + ~tree_decl_command (void); + + tree_decl_init_list *initializer_list (void) { return init_list; } + + void accept (tree_walker& tw); + + string name (void) { return cmd_name; } + +protected: + + // The name of this command -- global, static, etc. + string cmd_name; + + // TRUE if this command has been evaluated. + bool initialized; + + // The list of variables or initializers in this declaration command. + tree_decl_init_list *init_list; +}; + +// Global. + +class +tree_global_command : public tree_decl_command { public: tree_global_command (int l = -1, int c = -1) - : tree_command (l, c), init_list (0) { } + : tree_decl_command ("global", l, c) { } - tree_global_command (tree_global_init_list *t, int l = -1, int c = -1) - : tree_command (l, c), init_list (t) { } + tree_global_command (tree_decl_init_list *t, int l = -1, int c = -1) + : tree_decl_command ("global", t, l, c) { } - ~tree_global_command (void); + ~tree_global_command (void) { } void eval (void); +}; - tree_global_init_list *initializer_list (void) { return init_list; } +// Static. - void accept (tree_walker& tw); +class +tree_static_command : public tree_decl_command +{ +public: -private: + tree_static_command (int l = -1, int c = -1) + : tree_decl_command ("static", l, c) { } - // The list of global variables or initializers in this global - // command. - tree_global_init_list *init_list; + tree_static_command (tree_decl_init_list *t, int l = -1, int c = -1) + : tree_decl_command ("static", t, l, c) { } + + ~tree_static_command (void) { } + + void eval (void); }; // While. diff --git a/src/pt-fvc.cc b/src/pt-fvc.cc --- a/src/pt-fvc.cc +++ b/src/pt-fvc.cc @@ -295,6 +295,13 @@ } void +tree_identifier::mark_as_static (void) +{ + if (sym) + sym->mark_as_static (); +} + +void tree_identifier::mark_as_formal_parameter (void) { if (sym) diff --git a/src/pt-fvc.h b/src/pt-fvc.h --- a/src/pt-fvc.h +++ b/src/pt-fvc.h @@ -81,6 +81,8 @@ void link_to_global (void); + void mark_as_static (void); + void mark_as_formal_parameter (void); void mark_for_possible_ans_assign (void) diff --git a/src/pt-misc.cc b/src/pt-misc.cc --- a/src/pt-misc.cc +++ b/src/pt-misc.cc @@ -428,58 +428,38 @@ tw.visit_return_list (*this); } -// Global. +// Declarations (global, static, etc.). -tree_global::~tree_global (void) +tree_decl_elt::~tree_decl_elt (void) { delete id; delete ass_expr; } void -tree_global::eval (void) +tree_decl_elt::accept (tree_walker& tw) { - if (id) - { - id->link_to_global (); - } - else if (ass_expr) + tw.visit_decl_elt (*this); +} + +// Initializer lists for declaration statements. + +void +tree_decl_init_list::eval (tree_decl_elt::eval_fcn f, bool skip_init) +{ + for (Pix p = first (); p != 0; next (p)) { - tree_identifier *idnt = 0; + f (*(this->operator () (p)), skip_init); - if (ass_expr->left_hand_side_is_identifier_only () - && (idnt = ass_expr->left_hand_side_id ())) - { - idnt->link_to_global (); - ass_expr->eval (false); - } - else - error ("global: unable to make individual structure elements global"); + if (error_state) + break; } } void -tree_global::accept (tree_walker& tw) -{ - tw.visit_global (*this); -} - -// Global initializer lists. - -void -tree_global_init_list::eval (void) +tree_decl_init_list::accept (tree_walker& tw) { - for (Pix p = first (); p != 0; next (p)) - { - tree_global *t = this->operator () (p); - t->eval (); - } -} - -void -tree_global_init_list::accept (tree_walker& tw) -{ - tw.visit_global_init_list (*this); + tw.visit_decl_init_list (*this); } // If. diff --git a/src/pt-misc.h b/src/pt-misc.h --- a/src/pt-misc.h +++ b/src/pt-misc.h @@ -45,8 +45,8 @@ class tree_parameter_list; class tree_return_list; class tree_va_return_list; -class tree_global; -class tree_global_init_list; +class tree_decl_elt; +class tree_decl_init_list; class tree_if_clause; class tree_if_command_list; class tree_switch_case; @@ -254,23 +254,25 @@ ~tree_va_return_list (void) { } }; -// List of expressions that make up a global statement. +// List of expressions that make up a declaration statement. class -tree_global +tree_decl_elt { public: - tree_global (void) + typedef void (*eval_fcn) (tree_decl_elt &, bool); + + tree_decl_elt (void) : id (0), ass_expr (0) { } - tree_global (tree_identifier *i) + tree_decl_elt (tree_identifier *i) : id (i), ass_expr (0) { } - tree_global (tree_simple_assignment_expression *ass) + tree_decl_elt (tree_simple_assignment_expression *ass) : id (0), ass_expr (ass) { } - ~tree_global (void); + ~tree_decl_elt (void); void eval (void); @@ -284,7 +286,7 @@ // Only one of id or ass_expr can be valid at once. - // An identifier to make global. + // An identifier to tag with the declared property. tree_identifier *id; // An assignemnt expression. Valid only if the left hand side of @@ -293,26 +295,26 @@ }; class -tree_global_init_list : public SLList +tree_decl_init_list : public SLList { public: - tree_global_init_list (void) - : SLList () { } + tree_decl_init_list (void) + : SLList () { } - tree_global_init_list (tree_global *t) - : SLList () { append (t); } + tree_decl_init_list (tree_decl_elt *t) + : SLList () { append (t); } - ~tree_global_init_list (void) + ~tree_decl_init_list (void) { while (! empty ()) { - tree_global *t = remove_front (); + tree_decl_elt *t = remove_front (); delete t; } } - void eval (void); + void eval (tree_decl_elt::eval_fcn, bool); void accept (tree_walker& tw); }; diff --git a/src/pt-pr-code.cc b/src/pt-pr-code.cc --- a/src/pt-pr-code.cc +++ b/src/pt-pr-code.cc @@ -142,6 +142,54 @@ } void +tree_print_code::visit_decl_command (tree_decl_command& cmd) +{ + indent (); + + os << cmd.name () << " "; + + tree_decl_init_list *init_list = cmd.initializer_list (); + + if (init_list) + init_list->accept (*this); +} + +void +tree_print_code::visit_decl_elt (tree_decl_elt& cmd) +{ + tree_identifier *id = cmd.ident (); + + if (id) + id->accept (*this); + + tree_simple_assignment_expression *ass_expr = cmd.assign_expr (); + + if (ass_expr) + ass_expr->accept (*this); +} + +void +tree_print_code::visit_decl_init_list (tree_decl_init_list& lst) +{ + Pix p = lst.first (); + + while (p) + { + tree_decl_elt *elt = lst (p); + + lst.next (p); + + if (elt) + { + elt->accept (*this); + + if (p) + os << ", "; + } + } +} + +void tree_print_code::visit_for_command (tree_for_command& cmd) { indent (); @@ -278,54 +326,6 @@ } void -tree_print_code::visit_global (tree_global& cmd) -{ - tree_identifier *id = cmd.ident (); - - if (id) - id->accept (*this); - - tree_simple_assignment_expression *ass_expr = cmd.assign_expr (); - - if (ass_expr) - ass_expr->accept (*this); -} - -void -tree_print_code::visit_global_command (tree_global_command& cmd) -{ - indent (); - - os << "global "; - - tree_global_init_list *init_list = cmd.initializer_list (); - - if (init_list) - init_list->accept (*this); -} - -void -tree_print_code::visit_global_init_list (tree_global_init_list& lst) -{ - Pix p = lst.first (); - - while (p) - { - tree_global *elt = lst (p); - - lst.next (p); - - if (elt) - { - elt->accept (*this); - - if (p) - os << ", "; - } - } -} - -void tree_print_code::visit_identifier (tree_identifier& id) { indent (); @@ -413,77 +413,6 @@ } void -tree_print_code::visit_switch_case (tree_switch_case& cs) -{ - indent (); - - if (cs.is_default_case ()) - os << "otherwise"; - else - os << "case "; - - tree_expression *label = cs.case_label (); - - if (label) - label->accept (*this); - - newline (); - - increment_indent_level (); - - tree_statement_list *list = cs.commands (); - - if (list) - { - list->accept (*this); - - decrement_indent_level (); - } -} - -void -tree_print_code::visit_switch_case_list (tree_switch_case_list& lst) -{ - Pix p = lst.first (); - - while (p) - { - tree_switch_case *elt = lst (p); - - if (elt) - elt->accept (*this); - - lst.next (p); - } -} - -void -tree_print_code::visit_switch_command (tree_switch_command& cmd) -{ - indent (); - - os << "switch "; - - tree_expression *expr = cmd.switch_value (); - - if (expr) - expr->accept (*this); - - newline (); - - increment_indent_level (); - - tree_switch_case_list *list = cmd.case_list (); - - if (list) - list->accept (*this); - - indent (); - - os << "endswitch"; -} - -void tree_print_code::visit_index_expression (tree_index_expression& expr) { indent (); @@ -1005,6 +934,77 @@ } void +tree_print_code::visit_switch_case (tree_switch_case& cs) +{ + indent (); + + if (cs.is_default_case ()) + os << "otherwise"; + else + os << "case "; + + tree_expression *label = cs.case_label (); + + if (label) + label->accept (*this); + + newline (); + + increment_indent_level (); + + tree_statement_list *list = cs.commands (); + + if (list) + { + list->accept (*this); + + decrement_indent_level (); + } +} + +void +tree_print_code::visit_switch_case_list (tree_switch_case_list& lst) +{ + Pix p = lst.first (); + + while (p) + { + tree_switch_case *elt = lst (p); + + if (elt) + elt->accept (*this); + + lst.next (p); + } +} + +void +tree_print_code::visit_switch_command (tree_switch_command& cmd) +{ + indent (); + + os << "switch "; + + tree_expression *expr = cmd.switch_value (); + + if (expr) + expr->accept (*this); + + newline (); + + increment_indent_level (); + + tree_switch_case_list *list = cmd.case_list (); + + if (list) + list->accept (*this); + + indent (); + + os << "endswitch"; +} + +void tree_print_code::visit_try_catch_command (tree_try_catch_command& cmd) { indent (); diff --git a/src/pt-pr-code.h b/src/pt-pr-code.h --- a/src/pt-pr-code.h +++ b/src/pt-pr-code.h @@ -56,6 +56,12 @@ void visit_continue_command (tree_continue_command&); + void visit_decl_command (tree_decl_command&); + + void visit_decl_elt (tree_decl_elt&); + + void visit_decl_init_list (tree_decl_init_list&); + void visit_for_command (tree_for_command&); void visit_function (tree_function&); @@ -64,12 +70,6 @@ void visit_function_trailer (tree_function&); - void visit_global (tree_global&); - - void visit_global_command (tree_global_command&); - - void visit_global_init_list (tree_global_init_list&); - void visit_identifier (tree_identifier&); void visit_if_clause (tree_if_clause&); @@ -78,12 +78,6 @@ void visit_if_command_list (tree_if_command_list&); - void visit_switch_case (tree_switch_case&); - - void visit_switch_case_list (tree_switch_case_list&); - - void visit_switch_command (tree_switch_command&); - void visit_index_expression (tree_index_expression&); void visit_indirect_ref (tree_indirect_ref&); @@ -130,6 +124,12 @@ void visit_subplot_using (subplot_using&); + void visit_switch_case (tree_switch_case&); + + void visit_switch_case_list (tree_switch_case_list&); + + void visit_switch_command (tree_switch_command&); + void visit_try_catch_command (tree_try_catch_command&); void visit_unary_expression (tree_unary_expression&); diff --git a/src/pt-walk.h b/src/pt-walk.h --- a/src/pt-walk.h +++ b/src/pt-walk.h @@ -57,21 +57,21 @@ visit_continue_command (tree_continue_command&) = 0; virtual void + visit_decl_command (tree_decl_command&) = 0; + + virtual void + visit_decl_elt (tree_decl_elt&) = 0; + + virtual void + visit_decl_init_list (tree_decl_init_list&) = 0; + + virtual void visit_for_command (tree_for_command&) = 0; virtual void visit_function (tree_function&) = 0; virtual void - visit_global (tree_global&) = 0; - - virtual void - visit_global_command (tree_global_command&) = 0; - - virtual void - visit_global_init_list (tree_global_init_list&) = 0; - - virtual void visit_identifier (tree_identifier&) = 0; virtual void diff --git a/src/symtab.cc b/src/symtab.cc --- a/src/symtab.cc +++ b/src/symtab.cc @@ -237,6 +237,7 @@ { formal_param = 0; linked_to_global = 0; + tagged_static = 0; sv_fcn = 0; definition = 0; next_elem = 0; @@ -547,7 +548,7 @@ definition = 0; linked_to_global = 0; } - else + else if (! tagged_static) { symbol_def *old_def = pop_def (); count = maybe_delete (old_def); @@ -597,6 +598,23 @@ return linked_to_global; } +void +symbol_record::mark_as_static (void) +{ + if (is_linked_to_global ()) + error ("can't make global variable static"); + else if (is_formal_parameter ()) + error ("can't make formal parameter static"); + else + tagged_static = 1; +} + +int +symbol_record::is_static (void) const +{ + return tagged_static; +} + octave_value symbol_record::variable_value (void) const { @@ -649,11 +667,14 @@ void symbol_record::push_context (void) { - context.push (definition); - definition = 0; + if (! is_static ()) + { + context.push (definition); + definition = 0; - global_link_context.push (static_cast (linked_to_global)); - linked_to_global = 0; + global_link_context.push (static_cast (linked_to_global)); + linked_to_global = 0; + } } void diff --git a/src/symtab.h b/src/symtab.h --- a/src/symtab.h +++ b/src/symtab.h @@ -180,6 +180,9 @@ void mark_as_linked_to_global (void); int is_linked_to_global (void) const; + void mark_as_static (void); + int is_static (void) const; + octave_value variable_value (void) const; octave_value& variable_reference (void); @@ -194,6 +197,7 @@ unsigned formal_param : 1; unsigned linked_to_global : 1; + unsigned tagged_static : 1; string nm; sv_Function sv_fcn; diff --git a/src/variables.cc b/src/variables.cc --- a/src/variables.cc +++ b/src/variables.cc @@ -956,6 +956,12 @@ return; } + if (sr->is_static ()) + { + error ("can't make static variable `%s' global", nm.c_str ()); + return; + } + // There must be a better way to do this. XXX FIXME XXX if (sr->is_variable ())