# HG changeset patch # User jwe # Date 865193846 0 # Node ID 2ad9af85b89b49b47834b9f66104794d4daa7ee3 # Parent 1aeb8869e4642444417d1a7dc93cd03deaa54bfd [project @ 1997-06-01 19:34:20 by jwe] diff --git a/src/TEMPLATE-INST/SLStack-sym.cc b/src/TEMPLATE-INST/SLStack-sym.cc --- a/src/TEMPLATE-INST/SLStack-sym.cc +++ b/src/TEMPLATE-INST/SLStack-sym.cc @@ -44,12 +44,12 @@ extern template class SLStack; -template class SLNode; -template class SLList; +template class SLNode; +template class SLList; -template class Stack; +template class Stack; -template class SLStack; +template class SLStack; /* ;;; Local Variables: *** diff --git a/src/pt-all.h b/src/pt-all.h new file mode 100644 --- /dev/null +++ b/src/pt-all.h @@ -0,0 +1,58 @@ +/* + +Copyright (C) 1996, 1997 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave 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 Octave; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if !defined (octave_tree_all_h) +#define octave_tree_all_h 1 + +#include "pt.h" +#include "pt-arg-list.h" +#include "pt-assign.h" +#include "pt-binop.h" +#include "pt-check.h" +#include "pt-cmd.h" +#include "pt-colon.h" +#include "pt-const.h" +#include "pt-decl.h" +#include "pt-except.h" +#include "pt-exp.h" +#include "pt-id.h" +#include "pt-idx.h" +#include "pt-indir.h" +#include "pt-jump.h" +#include "pt-loop.h" +#include "pt-mat.h" +#include "pt-misc.h" +#include "pt-plot.h" +#include "pt-pr-code.h" +#include "pt-select.h" +#include "pt-stmt.h" +#include "pt-unop.h" +#include "pt-pr-code.h" +#include "pt-walk.h" + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/pt-check.cc b/src/pt-check.cc new file mode 100644 --- /dev/null +++ b/src/pt-check.cc @@ -0,0 +1,637 @@ +/* + +Copyright (C) 1996, 1997 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave 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 Octave; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if defined (__GNUG__) +#pragma implementation +#endif + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "error.h" +#include "input.h" +#include "ov-usr-fcn.h" +#include "pt-all.h" + +void +tree_checker::visit_argument_list (tree_argument_list& lst) +{ + Pix p = lst.first (); + + while (p) + { + tree_expression *elt = lst (p); + + lst.next (p); + + if (elt) + { + if (do_lvalue_check && ! elt->lvalue_ok ()) + gripe ("invalid lvalue in multiple assignment", elt->line ()); + } + } +} + +void +tree_checker::visit_binary_expression (tree_binary_expression& expr) +{ + tree_expression *op1 = expr.lhs (); + + if (op1) + op1->accept (*this); + + tree_expression *op2 = expr.rhs (); + + if (op2) + op2->accept (*this); +} + +void +tree_checker::visit_break_command (tree_break_command&) +{ +} + +void +tree_checker::visit_colon_expression (tree_colon_expression& expr) +{ + tree_expression *op1 = expr.base (); + + if (op1) + op1->accept (*this); + + tree_expression *op3 = expr.increment (); + + if (op3) + op3->accept (*this); + + tree_expression *op2 = expr.limit (); + + if (op2) + op2->accept (*this); +} + +void +tree_checker::visit_continue_command (tree_continue_command&) +{ +} + +void +tree_checker::visit_decl_command (tree_decl_command& cmd) +{ + tree_decl_init_list *init_list = cmd.initializer_list (); + + if (init_list) + init_list->accept (*this); +} + +void +tree_checker::visit_decl_elt (tree_decl_elt& cmd) +{ + tree_identifier *id = cmd.ident (); + + if (id) + id->accept (*this); + + tree_expression *expr = cmd.expression (); + + if (expr) + expr->accept (*this); +} + +void +tree_checker::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); + } +} + +void +tree_checker::visit_simple_for_command (tree_simple_for_command& cmd) +{ + tree_expression *lhs = cmd.left_hand_side (); + + if (lhs) + { + if (! lhs->lvalue_ok ()) + gripe ("invalid lvalue in for command", cmd.line ()); + } + + tree_expression *expr = cmd.control_expr (); + + if (expr) + expr->accept (*this); + + tree_statement_list *list = cmd.body (); + + if (list) + list->accept (*this); +} + +void +tree_checker::visit_complex_for_command (tree_complex_for_command& cmd) +{ + tree_argument_list *lhs = cmd.left_hand_side (); + + if (lhs) + { + int len = lhs->length (); + + if (len == 0 || lhs > 2) + gripe ("invalid number of output arguments in for command", + cmd.line ()); + + do_lvalue_check = true; + + lhs->accept (*this); + + do_lvalue_check = false; + } + + tree_expression *expr = cmd.control_expr (); + + if (expr) + expr->accept (*this); + + tree_statement_list *list = cmd.body (); + + if (list) + list->accept (*this); +} + +void +tree_checker::visit_octave_user_function (octave_user_function& fcn) +{ + tree_statement_list *cmd_list = fcn.body (); + + if (cmd_list) + cmd_list->accept (*this); +} + +void +tree_checker::visit_identifier (tree_identifier& /* id */) +{ +} + +void +tree_checker::visit_if_clause (tree_if_clause& cmd) +{ + tree_expression *expr = cmd.condition (); + + if (expr) + expr->accept (*this); + + tree_statement_list *list = cmd.commands (); + + if (list) + list->accept (*this); +} + +void +tree_checker::visit_if_command (tree_if_command& cmd) +{ + tree_if_command_list *list = cmd.cmd_list (); + + if (list) + list->accept (*this); +} + +void +tree_checker::visit_if_command_list (tree_if_command_list& lst) +{ + Pix p = lst.first (); + + while (p) + { + tree_if_clause *elt = lst (p); + + if (elt) + elt->accept (*this); + + lst.next (p); + } +} + +void +tree_checker::visit_index_expression (tree_index_expression& expr) +{ + tree_expression *e = expr.expression (); + + if (e) + e->accept (*this); + + tree_argument_list *list = expr.arg_list (); + + if (list) + list->accept (*this); +} + +void +tree_checker::visit_indirect_ref (tree_indirect_ref& expr) +{ + tree_expression *e = expr.expression (); + + if (e) + e->accept (*this); +} + +void +tree_checker::visit_matrix (tree_matrix& lst) +{ + Pix p = lst.first (); + + while (p) + { + tree_argument_list *elt = lst (p); + + lst.next (p); + + if (elt) + elt->accept (*this); + } +} + +void +tree_checker::visit_multi_assignment (tree_multi_assignment& expr) +{ + tree_argument_list *lhs = expr.left_hand_side (); + + if (lhs) + { + do_lvalue_check = true; + + lhs->accept (*this); + + do_lvalue_check = false; + } + + tree_expression *rhs = expr.right_hand_side (); + + if (rhs) + rhs->accept (*this); +} + +void +tree_checker::visit_no_op_command (tree_no_op_command& /* cmd */) +{ +} + +void +tree_checker::visit_constant (tree_constant& /* val */) +{ +} + +void +tree_checker::visit_parameter_list (tree_parameter_list& lst) +{ + Pix p = lst.first (); + + while (p) + { + tree_identifier *elt = lst (p); + + lst.next (p); + + if (elt) + elt->accept (*this); + } +} + +void +tree_checker::visit_plot_command (tree_plot_command& cmd) +{ + plot_limits *range = cmd.limits (); + + if (range) + range->accept (*this); + + subplot_list *plot_list = cmd.subplots (); + + if (plot_list) + plot_list->accept (*this); +} + +void +tree_checker::visit_plot_limits (plot_limits& cmd) +{ + plot_range *x_range = cmd.x_limits (); + + if (x_range) + x_range->accept (*this); + + plot_range *y_range = cmd.y_limits (); + + if (y_range) + y_range->accept (*this); + + plot_range *z_range = cmd.z_limits (); + + if (z_range) + z_range->accept (*this); +} + +void +tree_checker::visit_plot_range (plot_range& cmd) +{ + tree_expression *lower = cmd.lower_bound (); + + if (lower) + lower->accept (*this); + + tree_expression *upper = cmd.upper_bound (); + + if (upper) + upper->accept (*this); +} + +void +tree_checker::visit_postfix_expression (tree_postfix_expression& expr) +{ + tree_expression *e = expr.operand (); + + if (e) + e->accept (*this); +} + +void +tree_checker::visit_prefix_expression (tree_prefix_expression& expr) +{ + tree_expression *e = expr.operand (); + + if (e) + e->accept (*this); +} + +void +tree_checker::visit_return_command (tree_return_command&) +{ +} + +void +tree_checker::visit_return_list (tree_return_list& lst) +{ + Pix p = lst.first (); + + while (p) + { + tree_index_expression *elt = lst (p); + + lst.next (p); + + if (elt) + elt->accept (*this); + } +} + +void +tree_checker::visit_simple_assignment (tree_simple_assignment& expr) +{ + tree_expression *lhs = expr.left_hand_side (); + + if (lhs) + { + if (! lhs->lvalue_ok ()) + gripe ("invalid lvalue in assignment", expr.line ()); + } + + tree_expression *rhs = expr.right_hand_side (); + + if (rhs) + rhs->accept (*this); +} + +void +tree_checker::visit_statement (tree_statement& stmt) +{ + tree_command *cmd = stmt.command (); + + if (cmd) + cmd->accept (*this); + else + { + tree_expression *expr = stmt.expression (); + + if (expr) + expr->accept (*this); + } +} + +void +tree_checker::visit_statement_list (tree_statement_list& lst) +{ + for (Pix p = lst.first (); p != 0; lst.next (p)) + { + tree_statement *elt = lst (p); + + if (elt) + elt->accept (*this); + } +} + +void +tree_checker::visit_subplot (subplot& cmd) +{ + tree_expression *sp_plot_data = cmd.plot_data (); + + if (sp_plot_data) + sp_plot_data->accept (*this); + + subplot_using *sp_using_clause = cmd.using_clause (); + + if (sp_using_clause) + sp_using_clause->accept (*this); + + tree_expression *sp_title_clause = cmd.title_clause (); + + if (sp_title_clause) + sp_title_clause->accept (*this); + + subplot_style *sp_style_clause = cmd.style_clause (); + + if (sp_style_clause) + sp_style_clause->accept (*this); +} + +void +tree_checker::visit_subplot_list (subplot_list& lst) +{ + Pix p = lst.first (); + + while (p) + { + subplot *elt = lst (p); + + lst.next (p); + + if (elt) + elt->accept (*this); + } +} + +void +tree_checker::visit_subplot_style (subplot_style& cmd) +{ + tree_expression *sp_linetype = cmd.linetype (); + + if (sp_linetype) + sp_linetype->accept (*this); + + tree_expression *sp_pointtype = cmd.pointtype (); + + if (sp_pointtype) + sp_pointtype->accept (*this); +} + +void +tree_checker::visit_subplot_using (subplot_using& cmd) +{ + int qual_count = cmd.qualifier_count (); + + if (qual_count > 0) + { + tree_expression **x = cmd.qualifiers (); + + for (int i = 0; i < qual_count; i++) + { + if (x[i]) + x[i]->accept (*this); + } + } + else + { + tree_expression *scanf_fmt = cmd.scanf_format (); + + if (scanf_fmt) + scanf_fmt->accept (*this); + } +} + +void +tree_checker::visit_switch_case (tree_switch_case& cs) +{ + tree_expression *label = cs.case_label (); + + if (label) + label->accept (*this); + + tree_statement_list *list = cs.commands (); + + if (list) + list->accept (*this); +} + +void +tree_checker::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_checker::visit_switch_command (tree_switch_command& cmd) +{ + tree_expression *expr = cmd.switch_value (); + + if (expr) + expr->accept (*this); + + tree_switch_case_list *list = cmd.case_list (); + + if (list) + list->accept (*this); +} + +void +tree_checker::visit_try_catch_command (tree_try_catch_command& cmd) +{ + tree_statement_list *try_code = cmd.body (); + + if (try_code) + try_code->accept (*this); + + tree_statement_list *catch_code = cmd.cleanup (); + + if (catch_code) + catch_code->accept (*this); +} + +void +tree_checker::visit_unwind_protect_command + (tree_unwind_protect_command& cmd) +{ + tree_statement_list *unwind_protect_code = cmd.body (); + + if (unwind_protect_code) + unwind_protect_code->accept (*this); + + tree_statement_list *cleanup_code = cmd.cleanup (); + + if (cleanup_code) + cleanup_code->accept (*this); +} + +void +tree_checker::visit_while_command (tree_while_command& cmd) +{ + tree_expression *expr = cmd.condition (); + + if (expr) + expr->accept (*this); + + tree_statement_list *list = cmd.body (); + + if (list) + list->accept (*this); +} + +void +tree_checker::gripe (const string& msg, int line) +{ + if (curr_fcn_file_name.empty ()) + error ("%s", msg.c_str ()); + else + error ("%s: %d: %s", curr_fcn_file_name.c_str (), line, msg.c_str ()); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/pt-check.h b/src/pt-check.h new file mode 100644 --- /dev/null +++ b/src/pt-check.h @@ -0,0 +1,147 @@ +/* + +Copyright (C) 1996, 1997 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave 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 Octave; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if !defined (octave_tree_checker_h) +#define octave_tree_checker_h 1 + +#if defined (__GNUG__) +#pragma interface +#endif + +#include "pt-walk.h" + +// How to check the semantics of the code that the parse trees represent. + +class +tree_checker : public tree_walker +{ +public: + + tree_checker (void) + : do_lvalue_check (false) { } + + ~tree_checker (void) { } + + void visit_argument_list (tree_argument_list&); + + void visit_binary_expression (tree_binary_expression&); + + void visit_break_command (tree_break_command&); + + void visit_colon_expression (tree_colon_expression&); + + 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_simple_for_command (tree_simple_for_command&); + + void visit_complex_for_command (tree_complex_for_command&); + + void visit_octave_user_function (octave_user_function&); + + void visit_identifier (tree_identifier&); + + void visit_if_clause (tree_if_clause&); + + void visit_if_command (tree_if_command&); + + void visit_if_command_list (tree_if_command_list&); + + void visit_index_expression (tree_index_expression&); + + void visit_indirect_ref (tree_indirect_ref&); + + void visit_matrix (tree_matrix&); + + void visit_multi_assignment (tree_multi_assignment&); + + void visit_no_op_command (tree_no_op_command&); + + void visit_constant (tree_constant&); + + void visit_parameter_list (tree_parameter_list&); + + void visit_plot_command (tree_plot_command&); + + void visit_plot_limits (plot_limits&); + + void visit_plot_range (plot_range&); + + void visit_postfix_expression (tree_postfix_expression&); + + void visit_prefix_expression (tree_prefix_expression&); + + void visit_return_command (tree_return_command&); + + void visit_return_list (tree_return_list&); + + void visit_simple_assignment (tree_simple_assignment&); + + void visit_statement (tree_statement&); + + void visit_statement_list (tree_statement_list&); + + void visit_subplot (subplot&); + + void visit_subplot_list (subplot_list&); + + void visit_subplot_style (subplot_style&); + + 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_unwind_protect_command (tree_unwind_protect_command&); + + void visit_while_command (tree_while_command&); + +private: + + bool do_lvalue_check; + + void gripe (const string& msg, int line); + + // No copying! + + tree_checker (const tree_checker&); + + tree_checker& operator = (const tree_checker&); +}; + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/symtab.h b/src/symtab.h --- a/src/symtab.h +++ b/src/symtab.h @@ -27,61 +27,30 @@ #pragma interface #endif +#include + #include #include "SLStack.h" +#include "oct-alloc.h" #include "str-vec.h" #include "ov.h" -// Must be multiple of 2. -#define HASH_TABLE_SIZE 1024 -#define HASH_MASK (HASH_TABLE_SIZE - 1) - class octave_lvalue; class string_vector; -class symbol_def; class symbol_record; -class symbol_record_info; class symbol_table; -// Variables or functions. - -class symbol_def -{ - friend class symbol_record; - friend class symbol_record_info; - -public: - - symbol_def (void); - - symbol_def (const octave_value& val, unsigned int sym_type = 0); - - ~symbol_def (void) { } +// Individual records in a symbol table. - bool is_variable (void) const; - bool is_function (void) const; - bool is_text_function (void) const; - bool is_mapper_function (void) const; - bool is_user_variable (void) const; - bool is_user_function (void) const; - bool is_builtin_variable (void) const; - bool is_builtin_function (void) const; - bool is_map_element (const string& elts) const; - - void define (const octave_value& val, unsigned int sym_type); - - void protect (void); - void unprotect (void); - void make_eternal (void); - - octave_value& def (void); - string help (void) const; - void document (const string& h); +class +symbol_record +{ +public: enum TYPE { @@ -94,104 +63,221 @@ BUILTIN_VARIABLE = 32 }; - unsigned int symbol_type (void) { return type; } - - friend maybe_delete (symbol_def *def); - private: - unsigned int type : 6; - unsigned int eternal : 1; - unsigned int read_only : 1; + // Variables or functions. + + class symbol_def + { + public: + + symbol_def (const octave_value& val = octave_value (), + unsigned int sym_type = 0) + : symbol_type (sym_type), eternal (0), read_only (0), help_string (), + definition (val), next_elem (0), count (1) { } + + ~symbol_def (void) { } + + bool is_variable (void) const + { + return (symbol_type & symbol_record::USER_VARIABLE + || symbol_type & symbol_record::BUILTIN_VARIABLE); + } + + bool is_function (void) const + { + return (symbol_type & symbol_record::USER_FUNCTION + || symbol_type & symbol_record::BUILTIN_FUNCTION); + } + + bool is_user_variable (void) const + { return (symbol_type & symbol_record::USER_VARIABLE); } - string help_string; - octave_value definition; - symbol_def *next_elem; - int count; + bool is_text_function (void) const + { return (symbol_type & symbol_record::TEXT_FUNCTION); } + + bool is_mapper_function (void) const + { return (symbol_type & symbol_record::MAPPER_FUNCTION); } + + bool is_user_function (void) const + { return (symbol_type & symbol_record::USER_FUNCTION); } + + bool is_builtin_variable (void) const + { return (symbol_type & symbol_record::BUILTIN_VARIABLE); } - void init_state (void); + bool is_builtin_function (void) const + { return (symbol_type & symbol_record::BUILTIN_FUNCTION); } + + // XXX FIXME XXX + bool is_map_element (const string& /* elts */) const + { return false; } + + bool is_defined (void) const + { return definition.is_defined (); } + + bool is_read_only (void) const + { return read_only; } + + bool is_eternal (void) const + { return eternal; } - symbol_def (const symbol_def& sd); - symbol_def& operator = (const symbol_def& sd); -}; + void define (const octave_value& val, unsigned int sym_type) + { + definition = val; + symbol_type = sym_type; + } + + void protect (void) { read_only = 1; } + + void unprotect (void) { read_only = 0; } + + void make_eternal (void) { eternal = 1; } + + octave_value& def (void) { return definition; } + + string help (void) const { return help_string; } + + void document (const string& h) { help_string = h; } + + unsigned int type (void) { return symbol_type; } + + void *operator new (size_t size) + { return allocator.alloc (size); } + + void operator delete (void *p, size_t size) + { allocator.free (p, size); } + + static octave_allocator allocator; -// Individual records in a symbol table. + // The type of this symbol (see the enum above). + unsigned int symbol_type : 6; + + // Nonzero means this variable cannot be cleared. + unsigned int eternal : 1; + + // Nonzero means this variable cannot be given a new value. + unsigned int read_only : 1; + + // The doc string associated with this variable. + string help_string; + + // The value of this definition. See ov.h and related files. + octave_value definition; -class -symbol_record -{ - friend class symbol_record_info; + // Pointer to next definition in chain. This is used so that + // variables can hide function definitions, and so that the function + // definitions can reappear if the variable is cleared. + symbol_def *next_elem; + + // Reference count. + int count; + + // No copying! + + symbol_def (const symbol_def& sd); + + symbol_def& operator = (const symbol_def& sd); + }; public: - typedef int (*sv_function) (void); + typedef int (*change_function) (void); - symbol_record (void); - symbol_record (const string& n, symbol_record *nxt = 0); + symbol_record (void) + : formal_param (0), linked_to_global (0), tagged_static (0), + nm (), chg_fcn (0), definition (new symbol_def ()), + next_elem (0) { } + + symbol_record (const string& n, symbol_record *nxt) + : formal_param (0), linked_to_global (0), tagged_static (0), + nm (n), chg_fcn (0), definition (new symbol_def ()), + next_elem (nxt) { } ~symbol_record (void) { } - string name (void) const; - string help (void) const; + string name (void) const { return nm; } - octave_value& def (void); + string help (void) const { return definition->help (); } + + octave_value& def (void) { return definition->def (); } void rename (const string& new_name); - bool is_function (void) const; - bool is_user_function (void) const; - bool is_text_function (void) const; - bool is_mapper_function (void) const; - bool is_builtin_function (void) const; - bool is_variable (void) const; - bool is_user_variable (void) const; - bool is_builtin_variable (void) const; - bool is_map_element (const string& elts) const; + bool is_function (void) const + { return definition->is_function (); } + + bool is_text_function (void) const + { return definition->is_text_function (); } + + bool is_mapper_function (void) const + { return definition->is_mapper_function (); } + + bool is_user_function (void) const + { return definition->is_user_function (); } - unsigned int type (void) const; + bool is_builtin_function (void) const + { return definition->is_builtin_function (); } + + bool is_variable (void) const + { return definition->is_variable (); } - bool is_defined (void) const; - bool is_read_only (void) const; - bool is_eternal (void) const; + bool is_user_variable (void) const + { return definition->is_user_variable (); } + + bool is_builtin_variable (void) const + { return definition->is_builtin_variable (); } + + bool is_map_element (const string& elts) const + { return definition->is_map_element (elts); } - void protect (void); - void unprotect (void); - void make_eternal (void); + unsigned int type (void) const { return definition->type (); } + + bool is_defined (void) const { return definition->is_defined (); } + + bool is_read_only (void) const { return definition->is_read_only (); } - void set_sv_function (sv_function f); + bool is_eternal (void) const { return definition->is_eternal (); } + + void protect (void) { definition->protect (); } - int define (const octave_value& v, - unsigned int sym_type = symbol_def::USER_VARIABLE); + void unprotect (void) { definition->unprotect (); } + + void make_eternal (void) { definition->make_eternal (); } - int define_as_fcn (const octave_value& v); + void set_change_function (change_function f) { chg_fcn = f; } - int define_builtin_var (const octave_value& v); + void define (const octave_value& v, unsigned int sym_type = USER_VARIABLE); + + void define_builtin_var (const octave_value& v); - int define (octave_function *f, unsigned int sym_type); + bool define_as_fcn (const octave_value& v); + + bool define (octave_function *f, unsigned int sym_type); - void document (const string& h); + void document (const string& h) { definition->document (h); } - int clear (void); + void clear (void); void alias (symbol_record *s, bool force = false); void mark_as_formal_parameter (void); - bool is_formal_parameter (void) const; + bool is_formal_parameter (void) const { return formal_param; } void mark_as_linked_to_global (void); - bool is_linked_to_global (void) const; + bool is_linked_to_global (void) const { return linked_to_global; } void mark_as_static (void); - bool is_static (void) const; + bool is_static (void) const { return tagged_static; } octave_value& variable_value (void); octave_lvalue variable_reference (void); - symbol_record *next (void) const; + symbol_record *next (void) const { return next_elem; } - void chain (symbol_record *s); + void chain (symbol_record *s) { next_elem = s; } void push_context (void); + void pop_context (void); private: @@ -201,25 +287,31 @@ unsigned int tagged_static : 1; string nm; - sv_function sv_fcn; + change_function chg_fcn; symbol_def *definition; symbol_record *next_elem; -// This should maybe be one stack with a structure containing all the -// items we need to save for recursive calls... + // This should maybe be one stack with a structure containing all the + // items we need to save for recursive calls... SLStack context; SLStack global_link_context; - void init_state (void); - - int read_only_error (const char *action); + bool read_only_error (const char *action); void push_def (symbol_def *sd); - symbol_def *pop_def (void); + + void remove_top_def (void); + + void replace_all_defs (symbol_def *sd); + + // No copying! + + symbol_record (const symbol_record& s); symbol_record& operator = (const symbol_record& s); }; +#if 0 // A structure for handling verbose information about a symbol_record. class @@ -266,6 +358,7 @@ string nm; string const_type; }; +#endif // A symbol table. @@ -274,22 +367,31 @@ #define SYMTAB_ALL_SCOPES (SYMTAB_LOCAL_SCOPE | SYMTAB_GLOBAL_SCOPE) -#define SYMTAB_ALL_TYPES (symbol_def::USER_FUNCTION \ - | symbol_def::USER_VARIABLE \ - | symbol_def::BUILTIN_FUNCTION \ - | symbol_def::TEXT_FUNCTION \ - | symbol_def::MAPPER_FUNCTION \ - | symbol_def::BUILTIN_VARIABLE) +#define SYMTAB_ALL_TYPES (symbol_record::USER_FUNCTION \ + | symbol_record::USER_VARIABLE \ + | symbol_record::BUILTIN_FUNCTION \ + | symbol_record::TEXT_FUNCTION \ + | symbol_record::MAPPER_FUNCTION \ + | symbol_record::BUILTIN_VARIABLE) -#define SYMTAB_VARIABLES (symbol_def::USER_VARIABLE \ - | symbol_def::BUILTIN_VARIABLE) +#define SYMTAB_VARIABLES (symbol_record::USER_VARIABLE \ + | symbol_record::BUILTIN_VARIABLE) class symbol_table { public: - symbol_table (void); + symbol_table (unsigned int tab_size = 128) + : table_size (tab_size), table (new symbol_record [table_size]) + { + assert ((tab_size % 2) == 0); + } + + ~symbol_table (void) + { + delete [] table; + } symbol_record *lookup (const string& nm, bool insert = false, bool warn = false); @@ -297,15 +399,17 @@ void rename (const string& old_name, const string& new_name); void clear (bool clear_user_functions = true); - int clear (const string& nm, bool clear_user_functions = true); + bool clear (const string& nm, bool clear_user_functions = true); int size (void) const; +#if 0 symbol_record_info * long_list (int& count, const string_vector& pats = string_vector (), int npats = 0, bool sort = false, unsigned int type = SYMTAB_ALL_TYPES, unsigned int scope = SYMTAB_ALL_SCOPES) const; +#endif string_vector list (int& count, const string_vector& pats = string_vector (), @@ -313,23 +417,35 @@ unsigned int type = SYMTAB_ALL_TYPES, unsigned int scope = SYMTAB_ALL_SCOPES) const; + + int maybe_list (const char *header, const string_vector& argv, + int argc, ostream& os, bool show_verbose, + unsigned type, unsigned scope); + symbol_record **glob (int& count, const string& pat = string ("*"), unsigned int type = SYMTAB_ALL_TYPES, unsigned int scope = SYMTAB_ALL_SCOPES) const; void push_context (void); + void pop_context (void); + void print_stats (void); + private: + unsigned int table_size; + + symbol_record *table; + unsigned int hash (const string& s); - symbol_record table[HASH_TABLE_SIZE]; -}; + // No copying! -extern bool valid_identifier (const char *s); + symbol_table (const symbol_table&); -extern bool valid_identifier (const string& s); + symbol_table& operator = (const symbol_table&); +}; #endif diff --git a/src/variables.cc b/src/variables.cc --- a/src/variables.cc +++ b/src/variables.cc @@ -1196,82 +1196,6 @@ // List variable names. -static void -print_symbol_info_line (ostream& os, const symbol_record_info& s) -{ - os << (s.is_read_only () ? " -" : " w"); - os << (s.is_eternal () ? "- " : "d "); -#if 0 - os << (s.hides_fcn () ? "f" : (s.hides_builtin () ? "F" : "-")); -#endif - os.form (" %-16s", s.type_name ().c_str ()); - - int nr = s.rows (); - int nc = s.columns (); - - if (nr < 0) - os << " -"; - else - os.form ("%7d", nr); - - if (nc < 0) - os << " -"; - else - os.form ("%7d", nc); - - os << " " << s.name () << "\n"; -} - -static void -print_long_listing (ostream& os, symbol_record_info *s) -{ - if (! s) - return; - - symbol_record_info *ptr = s; - while (ptr->is_defined ()) - { - print_symbol_info_line (os, *ptr); - ptr++; - } -} - -static int -maybe_list (const char *header, const string_vector& argv, int argc, - ostream& os, bool show_verbose, symbol_table - *sym_tab, unsigned type, unsigned scope) -{ - int count; - int status = 0; - if (show_verbose) - { - symbol_record_info *symbols; - symbols = sym_tab->long_list (count, argv, argc, 1, type, scope); - if (symbols && count > 0) - { - os << "\n" << header << "\n\n" - << "prot type rows cols name\n" - << "==== ==== ==== ==== ====\n"; - - print_long_listing (os, symbols); - status = 1; - } - delete [] symbols; - } - else - { - string_vector symbols = sym_tab->list (count, argv, argc, 1, - type, scope); - if (symbols.length () > 0 && count > 0) - { - os << "\n" << header << "\n\n"; - symbols.list_in_columns (os); - status = 1; - } - } - return status; -} - DEFUN (document, args, , "document (NAME, STRING)\n\ \n\ @@ -1377,36 +1301,33 @@ if (show_builtins) { - pad_after += maybe_list ("*** built-in variables:", pats, npats, - octave_stdout, show_verbose, global_sym_tab, - symbol_def::BUILTIN_VARIABLE, - SYMTAB_ALL_SCOPES); + pad_after += global_sym_tab->maybe_list + ("*** built-in variables:", pats, npats, octave_stdout, + show_verbose, symbol_record::BUILTIN_VARIABLE, SYMTAB_ALL_SCOPES); - pad_after += maybe_list ("*** built-in functions:", pats, npats, - octave_stdout, show_verbose, global_sym_tab, - symbol_def::BUILTIN_FUNCTION, - SYMTAB_ALL_SCOPES); + pad_after += global_sym_tab->maybe_list + ("*** built-in functions:", pats, npats, octave_stdout, + show_verbose, symbol_record::BUILTIN_FUNCTION, SYMTAB_ALL_SCOPES); } if (show_functions) { - pad_after += maybe_list ("*** currently compiled functions:", - pats, npats, octave_stdout, show_verbose, - global_sym_tab, symbol_def::USER_FUNCTION, - SYMTAB_ALL_SCOPES); + pad_after += global_sym_tab->maybe_list + ("*** currently compiled functions:", pats, npats, + octave_stdout, show_verbose, symbol_record::USER_FUNCTION, + SYMTAB_ALL_SCOPES); } if (show_variables) { - pad_after += maybe_list ("*** local user variables:", pats, npats, - octave_stdout, show_verbose, curr_sym_tab, - symbol_def::USER_VARIABLE, - SYMTAB_LOCAL_SCOPE); + pad_after += curr_sym_tab->maybe_list + ("*** local user variables:", pats, npats, octave_stdout, + show_verbose, symbol_record::USER_VARIABLE, SYMTAB_LOCAL_SCOPE); - pad_after += maybe_list ("*** globally visible user variables:", - pats, npats, octave_stdout, show_verbose, - curr_sym_tab, symbol_def::USER_VARIABLE, - SYMTAB_GLOBAL_SCOPE); + pad_after += curr_sym_tab->maybe_list + ("*** globally visible user variables:", pats, npats, + octave_stdout, show_verbose, symbol_record::USER_VARIABLE, + SYMTAB_GLOBAL_SCOPE); } if (pad_after) @@ -1733,7 +1654,7 @@ SYMTAB_GLOBAL_SCOPE); fcns = global_sym_tab->list (fcount, 0, 0, 0, - symbol_def::USER_FUNCTION, + symbol_record::USER_FUNCTION, SYMTAB_ALL_SCOPES); }