changeset 33157:899647fde914 bytecode-interpreter

maint: merge default to bytecode-interpreter
author John W. Eaton <jwe@octave.org>
date Wed, 06 Mar 2024 13:02:42 -0500
parents 4035a1f71e07 (current diff) c23152b00d5f (diff)
children 5108f56fc8fc
files
diffstat 4 files changed, 136 insertions(+), 147 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/octave-value/ov-magic-int.cc	Wed Mar 06 11:34:10 2024 -0500
+++ b/libinterp/octave-value/ov-magic-int.cc	Wed Mar 06 13:02:42 2024 -0500
@@ -216,7 +216,7 @@
 }
 
 template <typename T>
-OCTAVE_NORETURN bool
+bool
 octave_base_magic_int<T>::load_ascii (std::istream&)
 {
   error ("octave_base_magic_int<T>::load_ascii: internal error");
@@ -232,7 +232,7 @@
 }
 
 template <typename T>
-OCTAVE_NORETURN bool
+bool
 octave_base_magic_int<T>::load_binary (std::istream&, bool,
                                        octave::mach_info::float_format)
 {
--- a/libinterp/parse-tree/lex.h	Wed Mar 06 11:34:10 2024 -0500
+++ b/libinterp/parse-tree/lex.h	Wed Mar 06 13:02:42 2024 -0500
@@ -669,9 +669,9 @@
 
   int handle_superclass_identifier ();
 
-  token * make_meta_identifier_token ();
+  token * make_meta_identifier_token (const std::string& cls);
 
-  token * make_fq_identifier_token ();
+  token * make_fq_identifier_token (const std::string& ident);
 
   int handle_identifier ();
 
@@ -689,6 +689,10 @@
 
   void warn_deprecated_syntax (const std::string& msg);
 
+  int syntax_error (const std::string& msg);
+  int syntax_error (const std::string& msg, const filepos& pos);
+  int syntax_error (const std::string& msg, const filepos& beg_pos, const filepos& end_pos);
+
   void push_token (token *);
 
   token * current_token ();
@@ -742,11 +746,9 @@
 
   int finish_command_arg ();
 
-  int handle_token (int tok_id, token *tok = nullptr);
+  int handle_token (int tok_id);
   int handle_token (token *tok);
 
-  int count_token (int tok_id);
-
   int count_token_internal (int tok_id);
 
   int show_token (int tok_id);
--- a/libinterp/parse-tree/lex.ll	Wed Mar 06 11:34:10 2024 -0500
+++ b/libinterp/parse-tree/lex.ll	Wed Mar 06 13:02:42 2024 -0500
@@ -688,7 +688,7 @@
 
         curr_lexer->push_start_state (MATRIX_START);
 
-        return curr_lexer->count_token ('[');
+        return curr_lexer->handle_token ('[');
       }
   }
 
@@ -1011,9 +1011,7 @@
       {
         // Use location of octal digits for error token.
         std::string msg {"invalid octal escape sequence in character string"};
-        octave::token *tok = new octave::token (LEXICAL_ERROR, msg, curr_lexer->m_tok_beg, curr_lexer->m_tok_end);
-
-        return curr_lexer->handle_token (tok);
+        return curr_lexer->syntax_error (msg);
       }
     else
       curr_lexer->m_string_text += static_cast<unsigned char> (result);
@@ -1115,11 +1113,7 @@
 
     // Use current file position for error token.
     std::string msg {"unterminated character string constant"};
-    octave::token *tok = new octave::token (LEXICAL_ERROR, msg, curr_lexer->m_filepos, curr_lexer->m_filepos);
-
-    curr_lexer->m_filepos.next_line ();
-
-    return curr_lexer->handle_token (tok);
+    return curr_lexer->syntax_error (msg, curr_lexer->m_filepos);
   }
 
 %{
@@ -1167,11 +1161,7 @@
 
     // Use current file position for error token.
     std::string msg {"unterminated character string constant"};
-    octave::token *tok = new octave::token (LEXICAL_ERROR, msg, curr_lexer->m_filepos, curr_lexer->m_filepos);
-
-    curr_lexer->m_filepos.next_line ();
-
-    return curr_lexer->handle_token (tok);
+    return curr_lexer->syntax_error (msg, curr_lexer->m_filepos);
   }
 
 %{
@@ -1185,7 +1175,14 @@
 
     curr_lexer->update_token_positions (yyleng);
 
-    octave::token *tok = curr_lexer->make_fq_identifier_token ();
+    std::string ident = yytext;
+
+    ident.erase (std::remove_if (ident.begin (), ident.end (), is_space_or_tab), ident.end ());
+
+    if (curr_lexer->fq_identifier_contains_keyword (ident))
+      return curr_lexer->syntax_error ("function, method, class, and package names may not be keywords");
+
+    octave::token *tok = curr_lexer->make_fq_identifier_token (ident);
 
     return curr_lexer->handle_token (tok);
   }
@@ -1341,7 +1338,17 @@
       {
         curr_lexer->update_token_positions (yyleng);
 
-        octave::token *tok = curr_lexer->make_meta_identifier_token ();
+        std::string txt = yytext;
+
+        txt.erase (std::remove_if (txt.begin (), txt.end (), is_space_or_tab), txt.end ());
+
+        // Eliminate leading '?'
+        std::string cls = txt.substr (1);
+
+        if (curr_lexer->fq_identifier_contains_keyword (cls))
+          return curr_lexer->syntax_error ("class and package names may not be keywords");
+
+        octave::token *tok = curr_lexer->make_meta_identifier_token (cls);
 
         return curr_lexer->handle_token (tok);
       }
@@ -1382,7 +1389,7 @@
                 curr_lexer->m_looking_at_function_handle++;
                 curr_lexer->m_looking_for_object_index = false;
 
-                return curr_lexer->count_token ('@');
+                return curr_lexer->handle_token ('@');
               }
             else
               {
@@ -1395,14 +1402,12 @@
                 if (octave::iskeyword (ident))
                   {
                     std::string msg {"function handles may not refer to keywords"};
-                    tok = new octave::token (LEXICAL_ERROR, msg, curr_lexer->m_tok_beg, curr_lexer->m_tok_end);
+                    return curr_lexer->syntax_error (msg);
                   }
-                else
-                  {
-                    curr_lexer->m_looking_for_object_index = true;
-
-                    tok = new octave::token (FCN_HANDLE, ident, curr_lexer->m_tok_beg, curr_lexer->m_tok_end);
-                  }
+
+                curr_lexer->m_looking_for_object_index = true;
+
+                tok = new octave::token (FCN_HANDLE, ident, curr_lexer->m_tok_beg, curr_lexer->m_tok_end);
 
                 return curr_lexer->handle_token (tok);
               }
@@ -1435,7 +1440,7 @@
 
         curr_lexer->m_at_beginning_of_statement = true;
 
-        return curr_lexer->count_token ('\n');
+        return curr_lexer->handle_token ('\n');
       }
     else if (curr_lexer->m_nesting_level.is_bracket_or_brace ())
       {
@@ -1444,9 +1449,7 @@
 
         // Use current file position for error token.
         std::string msg {"unexpected internal lexer error"};
-        octave::token *tok = new octave::token (LEXICAL_ERROR, msg, curr_lexer->m_filepos, curr_lexer->m_filepos);
-
-        return curr_lexer->handle_token (tok);
+        return curr_lexer->syntax_error (msg, curr_lexer->m_filepos);
       }
   }
 
@@ -1502,7 +1505,7 @@
                 else
                   {
                     curr_lexer->m_filepos.increment_column ();
-                    return curr_lexer->count_token (HERMITIAN);
+                    return curr_lexer->handle_token (HERMITIAN);
                   }
               }
           }
@@ -1518,7 +1521,7 @@
             else
               {
                 curr_lexer->m_filepos.increment_column ();
-                return curr_lexer->count_token (HERMITIAN);
+                return curr_lexer->handle_token (HERMITIAN);
               }
           }
       }
@@ -1708,7 +1711,7 @@
         curr_lexer->m_nesting_level.anon_fcn_body ();
       }
 
-    return curr_lexer->count_token (')');
+    return curr_lexer->handle_token (')');
   }
 
 "." {
@@ -1793,7 +1796,7 @@
 
         curr_lexer->push_start_state (MATRIX_START);
 
-        return curr_lexer->count_token ('{');
+        return curr_lexer->handle_token ('{');
       }
   }
 
@@ -1844,13 +1847,9 @@
             << octave::undo_string_escape (static_cast<char> (c))
             << "' (ASCII " << c << ")";
 
-        // Use current file position for error token.
-        std::string msg {"unexpected internal lexer error"};
-        octave::token *tok = new octave::token (LEXICAL_ERROR, buf.str (), msg, curr_lexer->m_filepos, curr_lexer->m_filepos);
-
-        curr_lexer->m_filepos.increment_column ();
-
-        return curr_lexer->handle_token (tok);
+        curr_lexer->update_token_positions (yyleng);
+
+        return curr_lexer->syntax_error (buf.str ());
       }
   }
 
@@ -2471,14 +2470,13 @@
 
     if (m_block_comment_nesting_level != 0)
       {
+        std::string msg {"block comment unterminated at end of input"};
 
         if ((m_reading_fcn_file || m_reading_script_file || m_reading_classdef_file)
             && ! m_fcn_file_name.empty ())
-          error ("block comment unterminated at end of input\n"
-                 "near line %d of file '%s.m'",
-                 m_filepos.line () - 1, m_fcn_file_name.c_str ());
-        else
-          error ("block comment unterminated at end of input");
+          msg += " near line " + std::to_string (m_filepos.line () - 1) + " of file '" + m_fcn_file_name + ".m'";
+
+        syntax_error (msg);
       }
 
     token *tok = new token (END_OF_INPUT, m_tok_beg, m_tok_end);
@@ -3010,9 +3008,7 @@
     if (bytes < 0)
       {
         std::string msg {"too many digits for binary constant"};
-        token *tok = new token (LEXICAL_ERROR, msg, m_tok_beg, m_tok_end);
-
-        return handle_token (tok);
+        return syntax_error (msg);
       }
 
     // FIXME: is there a better way?  Can uintmax_t be anything other
@@ -3214,9 +3210,7 @@
     if (bytes < 0)
       {
         std::string msg {"too many digits for hexadecimal constant"};
-        token *tok = new token (LEXICAL_ERROR, msg, m_tok_beg, m_tok_end);
-
-        return handle_token (tok);
+        return syntax_error (msg);
       }
 
     // Assert here because if yytext doesn't contain a valid number, we
@@ -3341,7 +3335,7 @@
 
     pop_start_state ();
 
-    return count_token (bracket_type);
+    return handle_token (bracket_type);
   }
 
   bool
@@ -3375,9 +3369,7 @@
     if (iskeyword (meth) || fq_identifier_contains_keyword (cls))
       {
         std::string msg {"method, class, and package names may not be keywords"};
-        token *tok = new token (LEXICAL_ERROR, msg, m_tok_beg, m_tok_end);
-
-        return handle_token (tok);
+        return syntax_error (msg);
       }
 
     token *tok = new token (SUPERCLASSREF, meth, cls, m_tok_beg, m_tok_end);
@@ -3388,64 +3380,31 @@
   }
 
   token *
-  base_lexer::make_meta_identifier_token ()
+  base_lexer::make_meta_identifier_token (const std::string& cls)
   {
-    std::string txt = flex_yytext ();
-
-    txt.erase (std::remove_if (txt.begin (), txt.end (), is_space_or_tab),
-               txt.end ());
-
-    // Eliminate leading '?'
-    std::string cls = txt.substr (1);
-
     // Token positions should have already been updated before this
     // function is called.
 
-    token *tok;
-
-    if (fq_identifier_contains_keyword (cls))
-      {
-        std::string msg {"class and package names may not be keywords"};
-        tok = new token (LEXICAL_ERROR, msg, m_tok_beg, m_tok_end);
-      }
-    else
-      {
-        m_looking_for_object_index = true;
-
-        tok = new token (METAQUERY, cls, m_tok_beg, m_tok_end);
-
-        m_filepos.increment_column (flex_yyleng ());
-      }
+    m_looking_for_object_index = true;
+
+    token *tok = new token (METAQUERY, cls, m_tok_beg, m_tok_end);
+
+    m_filepos.increment_column (flex_yyleng ());
 
     return tok;
   }
 
   token *
-  base_lexer::make_fq_identifier_token ()
+  base_lexer::make_fq_identifier_token (const std::string& ident)
   {
-    std::string txt = flex_yytext ();
-
-    txt.erase (std::remove_if (txt.begin (), txt.end (), is_space_or_tab),
-               txt.end ());
-
     // Token positions should have already been updated before this
     // function is called.
 
-    token *tok;
-
-    if (fq_identifier_contains_keyword (txt))
-      {
-        std::string msg {"function, method, class, and package names may not be keywords"};
-        tok = new token (LEXICAL_ERROR, msg, m_tok_beg, m_tok_end);
-      }
-    else
-      {
-        m_looking_for_object_index = true;
-
-        tok = new token (FQ_IDENT, txt, m_tok_beg, m_tok_end);
-
-        m_filepos.increment_column (flex_yyleng ());
-      }
+    m_looking_for_object_index = true;
+
+    token *tok = new token (FQ_IDENT, ident, m_tok_beg, m_tok_end);
+
+    m_filepos.increment_column (flex_yyleng ());
 
     return tok;
   }
@@ -3598,6 +3557,28 @@
                        m_filepos.line (), m_fcn_file_full_name.c_str ());
   }
 
+  int
+  base_lexer::syntax_error (const std::string& msg)
+  {
+    return syntax_error (msg, m_tok_beg, m_tok_end);
+  }
+
+  int
+  base_lexer::syntax_error (const std::string& msg, const filepos& pos)
+  {
+    return syntax_error (msg, pos, pos);
+  }
+
+  int
+  base_lexer::syntax_error (const std::string& msg, const filepos& beg_pos, const filepos& end_pos)
+  {
+    token *tok = new token (LEXICAL_ERROR, msg, beg_pos, end_pos);
+
+    push_token (tok);
+
+    return count_token_internal (tok->token_id ());
+  }
+
   void
   base_lexer::push_token (token *tok)
   {
@@ -3750,7 +3731,7 @@
   void
   base_lexer::fatal_error (const char *msg)
   {
-    error ("fatal lexer error: %s", msg);
+    ::error ("fatal lexer error: %s", msg);
   }
 
   bool
@@ -3950,12 +3931,9 @@
   }
 
   int
-  base_lexer::handle_token (int tok_id, token *tok)
+  base_lexer::handle_token (int tok_id)
   {
-    if (! tok)
-      tok = new token (tok_id, m_tok_beg, m_tok_end);
-
-    return handle_token (tok);
+    return handle_token (new token (tok_id, m_tok_beg, m_tok_end));
   }
 
   int
@@ -3967,12 +3945,6 @@
   }
 
   int
-  base_lexer::count_token (int tok_id)
-  {
-    return handle_token (new token (tok_id, m_tok_beg, m_tok_end));
-  }
-
-  int
   base_lexer::count_token_internal (int tok_id)
   {
     if (tok_id != '\n')
--- a/oct-conf-post-public.in.h	Wed Mar 06 11:34:10 2024 -0500
+++ b/oct-conf-post-public.in.h	Wed Mar 06 13:02:42 2024 -0500
@@ -32,32 +32,54 @@
 #define OCTAVE_BEGIN_NAMESPACE(name) namespace name {
 #define OCTAVE_END_NAMESPACE(name) }
 
-/* The C++ standard is evolving to allow attribute hints in a
-   compiler-independent manner.  In C++ 2011 support for noreturn was
-   added.  In C++ 2014 support for deprecated was added.  The Octave
-   code base has been future-proofed by using macros of the form
-   OCTAVE_ATTRIBUTE_NAME in place of vendor specific attribute
-   mechanisms.  As compilers evolve, the underlying implementation can
-   be changed with the macro definitions below.  FIXME: Update macros
-   to use C++ standard attribute syntax when Octave moves to C++ 2014
-   standard.  */
+/* We require C++17 now so it should be possible to use
+   [[deprecated(message)]], [[noreturn]], and [[unused]] unconditionally
+   but for now we'll keep the macros in case there is an issue.  Even if
+   we decide to use the C++ standard attributes directly in the Octave
+   sources without the macros, OCTAVE_DEPRECATED will still be useful to
+   provide consistent formatting of the version number.  */
 
 #if defined (__GNUC__)
-   /* The following attributes are used with gcc and clang compilers.  */
-#  if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
-#    define OCTAVE_DEPRECATED(ver, msg) __attribute__ ((__deprecated__ ("[" #ver "]: " msg)))
-#  else
-#    define OCTAVE_DEPRECATED(ver, msg) __attribute__ ((__deprecated__))
+
+#  if !defined (OCTAVE_DEPRECATED)
+#    if defined (__cplusplus)
+#      define OCTAVE_DEPRECATED(ver, msg) [[deprecated ("[" #ver "]: " msg)]]
+#    else
+#      define OCTAVE_DEPRECATED(ver, msg) __attribute__ ((__deprecated__ ("[" #ver "]: " msg)))
+#    endif
 #  endif
 #  define HAVE_OCTAVE_DEPRECATED_ATTR 1
 
-#  define OCTAVE_NORETURN __attribute__ ((__noreturn__))
-#  define HAVE_OCTAVE_NORETURN_ATTR 1
+#  if !defined (OCTAVE_FALLTHROUGH)
+#    if defined (__cplusplus)
+#      define OCTAVE_FALLTHROUGH [[fallthrough]]
+#    else
+#      define OCTAVE_FALLTHROUGH __attribute__ ((__fallthrough__))
+#    endif
+#    define HAVE_OCTAVE_FALLTHROUGH_ATTR 1
+#  endif
 
-#  define OCTAVE_UNUSED __attribute__ ((__unused__))
-#  define HAVE_OCTAVE_UNUSED_ATTR 1
+#  if !defined (OCTAVE_NORETURN)
+#    if defined (__cplusplus)
+#      define OCTAVE_NORETURN [[noreturn]]
+#    else
+#      define OCTAVE_NORETURN __attribute__ ((__noreturn__))
+#    endif
+#    define HAVE_OCTAVE_NORETURN_ATTR 1
+#  endif
+
+#  if !defined (OCTAVE_UNUSED)
+#    if defined (__cplusplus)
+#      define OCTAVE_UNUSED [[maybe_unused]]
+#    else
+#      define OCTAVE_UNUSED __attribute__ ((__unused__))
+#    endif
+#    define HAVE_OCTAVE_UNUSED_ATTR 1
+#  endif
+
 #else
 #  define OCTAVE_DEPRECATED(ver, msg)
+#  define OCTAVE_FALLTHROUGH ((void) 0)
 #  define OCTAVE_NORETURN
 #  define OCTAVE_UNUSED
 
@@ -67,7 +89,10 @@
 #endif
 
 /* Branch hint macros for use in if condititions.
-   Returns logical value of x. */
+   Returns logical value of x.
+
+   FIXME: With C++20, can we use [[likely]] and [[unlikely]]?  If so,
+   what is the purpose of the argument X in the macros below?  */
 #if defined (__GNUC__)
 #  define OCTAVE_LIKELY(x) __builtin_expect (!!(x), 1)
 #  define OCTAVE_UNLIKELY(x) __builtin_expect (!!(x), 0)
@@ -104,16 +129,6 @@
 /* #  undef HAVE_OCTAVE_FORMAT_PRINTF_ATTR */
 #endif
 
-#if ! defined (OCTAVE_FALLTHROUGH)
-#  if defined (__cplusplus) && __cplusplus > 201402L
-#    define OCTAVE_FALLTHROUGH [[fallthrough]]
-#  elif defined (__GNUC__) && __GNUC__ < 7
-#    define OCTAVE_FALLTHROUGH ((void) 0)
-#  else
-#    define OCTAVE_FALLTHROUGH __attribute__ ((__fallthrough__))
-#  endif
-#endif
-
 #if defined (__cplusplus)
 template <typename T>
 static inline void