Mercurial > octave
changeset 29724:c19f8cbe0fd5
initial implementation of parsing for arguments validaton block (bug #59405)
This change allows parsing of arguments validation blocks. Octave
should now accept the arguments block syntax in a mostly Matlab
compatible way. Multiple argument blocks are allowed. All arguments
blocks must appear before any other exectuable statements in a function.
Similar to "methods", "properties", etc., "arguments" is defined as a
keyword in the octave.gperf file so that converting "arguments" to the
ARGUMENTS token in the lexer and parser is simplified but it is not
really treated as a reserved keyword in the language. One known
problem with the current approach is that
function [...] = f (...)
arguments = 13;
...
end
will result in a parse error. A simple workaround is to place another
statement (that is not an arguments block) ahead of the "arguments =
..." line in the function. Fixing this problem generally might
require a different parsing method that allows a different type of
lookahead than we currently use.
NOTE: arguments blocks do not currently perform any actions.
Since they may provide default values and/or transform arguments to
different types or values, ignoring the arguments block can lead to
incorrect results.
Octave also currently allows arguments blocks in nested functions
though they should be rejected.
Special treatment of "arguments" and "endarguments" may be disabled by
defining the macro DISABLE_ARGUMENTS_VALIDATION_BLOCK. With this
macro defined, Octave's lexer will never return the ARGUMENTS token,
so the parser will fail to parse these program elements and the
behavior should be the same as prior to this change.
* pt-args-block.h, pt-args-block.cc: New files.
* libinterp/parse-tree/module.mk: Update.
* lex.h, lex.ll (lexical_feedback::m_arguments_is_keyword):
New member variable.
(lexical_feedback::reset): Reset m_arguments_is_keyword to false.
(iskeyword, Fiskeyword): Also handle "arguments" as a special case.
(base_lexer::make_keyword_token): Handle arguments and endarguments.
* parse.h, oct-parse.yy (base_parser::make_arguments_block,
base_parser::make_args_attribute_list,
base_parser::make_arg_validation,
base_parser::make_args_validation_list,
base_parser::append_args_validation_list,
base_parser::make_arg_size_spec,
base_parser::make_arg_validation_fcns): New functions.
(function_body, at_first_executable_stmt, function_body1,
arguments_block, arguments_beg, args_attr_list, args_validation_list,
arg_validation, size_spec, class_name, validation_fcns,
default_value): New non-terminals.
(ARGUMENTS): New token.
(function): Use new function_body and function_body1 non-terminals to
accept arguments blocks, but only at the beginning of a function.
(fcn_name): Set lexer.m_arguments_is_keyword to true after parsing
function name.
(param_list_beg): Set lexer.m_arguments_is_keyword to false while
parsing function parameter list.
(param_list_beg): Reset lexer.m_arguments_is_keyword to true after
parsing function parameter list.
(tree_arguments_block_type, tree_args_block_attribute_list_type,
tree_args_block_validation_list_type, tree_arg_size_spec_type,
tree_arg_validation_type, tree_arg_validation_fcns_type): New
non-terminal types. Also declare %destructors for them.
* octave.gperf (octave_kw_id): New IDs, arguments_kw and endarguments_kw.
Provide entries for arguments and endarguments keywords.
* pt-all.h: Include pt-args-block.h.
* pt-bp.h, pt-bp.cc (tree_breakpoint::visit_arguments_block,
tree_breakpoint::visit_args_block_attribute_list,
tree_breakpoint::visit_args_block_validation_list,
tree_breakpoint::visit_arg_validation,
tree_breakpoint::visit_arg_size_spec,
tree_breakpoint::visit_arg_validation_fcns): New virtual functions for
arguments block elements.
* pt-eval.h, pt-eval.cc (tree_evaluator::visit_arguments_block,
tree_evaluator::visit_args_block_attribute_list,
tree_evaluator::visit_args_block_validation_list,
tree_evaluator::visit_arg_validation,
tree_evaluator::visit_arg_size_spec,
tree_evaluator::visit_arg_validation_fcns): New virtual functions for
arguments block elements.
* pt-pr-code.h, pt-pr-code.cc (tree_print_code::visit_arguments_block,
tree_print_code::visit_args_block_attribute_list,
tree_print_code::visit_args_block_validation_list,
tree_print_code::visit_arg_validation,
tree_print_code::visit_arg_size_spec,
tree_print_code::visit_arg_validation_fcns): New virtual functions for
arguments block elements.
* pt-walk.h, pt-walk.cc (tree_walker::visit_arguments_block,
tree_walker::visit_args_block_attribute_list,
tree_walker::visit_args_block_validation_list,
tree_walker::visit_arg_validation, tree_walker::visit_arg_size_spec,
tree_walker::visit_arg_validation_fcns): New virtual functions for
arguments block elements.
* token.h (end_tok_type): New type, arguments_end.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 01 Jun 2021 13:34:57 -0400 |
parents | 6858992dfadf |
children | 80f31f0a51fa |
files | libinterp/parse-tree/lex.h libinterp/parse-tree/lex.ll libinterp/parse-tree/module.mk libinterp/parse-tree/oct-parse.yy libinterp/parse-tree/octave.gperf libinterp/parse-tree/parse.h libinterp/parse-tree/pt-all.h libinterp/parse-tree/pt-args-block.cc libinterp/parse-tree/pt-args-block.h libinterp/parse-tree/pt-bp.cc libinterp/parse-tree/pt-bp.h libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-eval.h libinterp/parse-tree/pt-pr-code.cc libinterp/parse-tree/pt-pr-code.h libinterp/parse-tree/pt-walk.cc libinterp/parse-tree/pt-walk.h libinterp/parse-tree/token.h |
diffstat | 18 files changed, 853 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/parse-tree/lex.h Tue Jun 01 16:57:40 2021 -0400 +++ b/libinterp/parse-tree/lex.h Tue Jun 01 13:34:57 2021 -0400 @@ -276,6 +276,7 @@ m_looking_at_matrix_or_assign_lhs (false), m_looking_for_object_index (false), m_looking_at_indirect_ref (false), + m_arguments_is_keyword (false), m_parsing_anon_fcn_body (false), m_parsing_class_method (false), m_parsing_classdef (false), @@ -391,6 +392,9 @@ // structure element. bool m_looking_at_indirect_ref; + // true means arguments is handled as keyword. + bool m_arguments_is_keyword; + // true means we are parsing the body of an anonymous function. bool m_parsing_anon_fcn_body;
--- a/libinterp/parse-tree/lex.ll Tue Jun 01 16:57:40 2021 -0400 +++ b/libinterp/parse-tree/lex.ll Tue Jun 01 13:34:57 2021 -0400 @@ -341,11 +341,12 @@ // "set" and "get" portions of the names using the same mechanism // as is used for keywords. However, they are not really keywords // in the language, so omit them from the list of possible - // keywords. Likewise for "enumeration", "events", "methods", and - // "properties". - + // keywords. Likewise for "arguments", "enumeration", "events", + // "methods", and "properties". + + // FIXME: The following check is duplicated in Fiskeyword. return (octave_kw_hash::in_word_set (s.c_str (), s.length ()) != nullptr - && ! (s == "set" || s == "get" + && ! (s == "set" || s == "get" || s == "arguments" || s == "enumeration" || s == "events" || s == "methods" || s == "properties")); } @@ -2141,7 +2142,8 @@ { std::string kword = wordlist[i].name; - if (! (kword == "set" || kword == "get" + // FIXME: The following check is duplicated in octave::iskeyword. + if (! (kword == "set" || kword == "get" || kword == "arguments" || kword == "enumeration" || kword == "events" || kword == "methods" || kword == "properties")) lst[j++] = kword; @@ -2237,6 +2239,7 @@ m_looking_at_matrix_or_assign_lhs = false; m_looking_for_object_index = false; m_looking_at_indirect_ref = false; + m_arguments_is_keyword = false; m_parsing_anon_fcn_body = false; m_parsing_class_method = false; m_parsing_classdef = false; @@ -2628,7 +2631,7 @@ m_filepos.increment_column (tok_len); } -bool + bool base_lexer::looking_at_space (void) { int c = text_yyinput (); @@ -2764,6 +2767,16 @@ m_at_beginning_of_statement = true; break; + case endarguments_kw: +#if defined (DISABLE_ARGUMENTS_VALIDATION_BLOCK) + return 0; +#else + tok_val = new token (endarguments_kw, token::arguments_end, m_tok_beg, + m_tok_end); + m_at_beginning_of_statement = true; + break; +#endif + case endclassdef_kw: tok_val = new token (endclassdef_kw, token::classdef_end, m_tok_beg, m_tok_end); @@ -2874,6 +2887,15 @@ } break; + case arguments_kw: +#if defined (DISABLE_ARGUMENTS_VALIDATION_BLOCK) + return 0; +#else + if (! m_arguments_is_keyword) + return 0; + break; +#endif + case spmd_kw: m_at_beginning_of_statement = true; break;
--- a/libinterp/parse-tree/module.mk Tue Jun 01 16:57:40 2021 -0400 +++ b/libinterp/parse-tree/module.mk Tue Jun 01 13:34:57 2021 -0400 @@ -13,6 +13,7 @@ %reldir%/pt-all.h \ %reldir%/pt-anon-scopes.h \ %reldir%/pt-arg-list.h \ + %reldir%/pt-args-block.h \ %reldir%/pt-array-list.h \ %reldir%/pt-assign.h \ %reldir%/pt-binop.h \ @@ -65,6 +66,7 @@ %reldir%/profiler.cc \ %reldir%/pt-anon-scopes.cc \ %reldir%/pt-arg-list.cc \ + %reldir%/pt-args-block.cc \ %reldir%/pt-array-list.cc \ %reldir%/pt-assign.cc \ %reldir%/pt-binop.cc \
--- a/libinterp/parse-tree/oct-parse.yy Tue Jun 01 16:57:40 2021 -0400 +++ b/libinterp/parse-tree/oct-parse.yy Tue Jun 01 13:34:57 2021 -0400 @@ -174,6 +174,12 @@ octave::tree_decl_command *tree_decl_command_type; octave::tree_statement *tree_statement_type; octave::tree_statement_list *tree_statement_list_type; + octave::tree_arguments_block *tree_arguments_block_type; + octave::tree_args_block_attribute_list *tree_args_block_attribute_list_type; + octave::tree_args_block_validation_list *tree_args_block_validation_list_type; + octave::tree_arg_size_spec *tree_arg_size_spec_type; + octave::tree_arg_validation *tree_arg_validation_type; + octave::tree_arg_validation_fcns *tree_arg_validation_fcns_type; octave_user_function *octave_user_function_type; octave::tree_classdef *tree_classdef_type; @@ -228,6 +234,7 @@ %token <tok_val> FQ_IDENT %token <tok_val> GET SET %token <tok_val> FCN +%token <tok_val> ARGUMENTS %token <tok_val> LEXICAL_ERROR %token <tok_val> END_OF_INPUT @@ -239,9 +246,9 @@ %type <dummy_type> indirect_ref_op decl_param_init %type <dummy_type> push_fcn_symtab push_script_symtab begin_file %type <dummy_type> param_list_beg param_list_end stmt_begin anon_fcn_begin -%type <dummy_type> parsing_local_fcns parse_error +%type <dummy_type> parsing_local_fcns parse_error at_first_executable_stmt %type <comment_type> stash_comment -%type <tok_val> function_beg classdef_beg +%type <tok_val> function_beg classdef_beg arguments_beg %type <punct_type> sep_no_nl opt_sep_no_nl nl opt_nl sep opt_sep %type <tree_type> input %type <tree_constant_type> string constant magic_colon @@ -277,7 +284,7 @@ %type <tree_decl_command_type> declaration %type <tree_statement_type> statement function_end %type <tree_statement_list_type> simple_list simple_list1 list list1 -%type <tree_statement_list_type> opt_list +%type <tree_statement_list_type> opt_list function_body function_body1 %type <tree_statement_list_type> opt_fcn_list fcn_list fcn_list1 %type <tree_classdef_attribute_type> attr %type <tree_classdef_attribute_list_type> attr_list attr_list1 @@ -296,6 +303,14 @@ %type <tree_classdef_enum_list_type> enum_list enum_list1 %type <tree_classdef_enum_block_type> enum_block %type <tree_function_def_type> method_decl method +%type <tree_arguments_block_type> arguments_block +%type <tree_args_block_attribute_list_type> args_attr_list +%type <tree_args_block_validation_list_type> args_validation_list +%type <tree_arg_validation_type> arg_validation +%type <tree_arg_size_spec_type> size_spec +%type <tree_identifier_type> class_name +%type <tree_arg_validation_fcns_type> validation_fcns +%type <tree_expression_type> default_value %type <octave_user_function_type> method_decl1 // Precedence and associativity. @@ -351,6 +366,12 @@ %destructor { delete $$; } <tree_decl_command_type> %destructor { delete $$; } <tree_statement_type> %destructor { delete $$; } <tree_statement_list_type> +%destructor { delete $$; } <tree_arguments_block_type> +%destructor { delete $$; } <tree_args_block_attribute_list_type> +%destructor { delete $$; } <tree_args_block_validation_list_type> +%destructor { delete $$; } <tree_arg_validation_type> +%destructor { delete $$; } <tree_arg_size_spec_type> +%destructor { delete $$; } <tree_arg_validation_fcns_type> %destructor { delete $$; } <octave_user_function_type> %destructor { delete $$; } <tree_classdef_type> @@ -1430,6 +1451,7 @@ $$ = 0; lexer.m_looking_at_parameter_list = true; + lexer.m_arguments_is_keyword = false; if (lexer.m_looking_at_function_handle) { @@ -1447,6 +1469,7 @@ $$ = 0; lexer.m_looking_at_parameter_list = false; + lexer.m_arguments_is_keyword = true; lexer.m_looking_for_object_index = false; } ; @@ -1654,32 +1677,37 @@ fcn_name : identifier { - $$ = parser.make_fcn_name ($1); - if (! $$) + if (! ($$ = parser.make_fcn_name ($1))) { // make_fcn_name deleted $1. YYABORT; } + + lexer.m_arguments_is_keyword = true; } | GET '.' identifier { OCTAVE_YYUSE ($1); OCTAVE_YYUSE ($2); + $$ = $3; + lexer.m_parsed_function_name.top () = true; lexer.m_maybe_classdef_get_set_method = false; lexer.m_parsing_classdef_get_method = true; - $$ = $3; + lexer.m_arguments_is_keyword = true; } | SET '.' identifier { OCTAVE_YYUSE ($1); OCTAVE_YYUSE ($2); + $$ = $3; + lexer.m_parsed_function_name.top () = true; lexer.m_maybe_classdef_get_set_method = false; lexer.m_parsing_classdef_set_method = true; - $$ = $3; + lexer.m_arguments_is_keyword = true; } ; @@ -1732,14 +1760,14 @@ ; function : function_beg stash_comment fcn_name - opt_param_list opt_sep opt_list function_end + opt_param_list opt_sep function_body function_end { OCTAVE_YYUSE ($5); $$ = parser.make_function ($1, nullptr, $3, $4, $6, $7, $2); } | function_beg stash_comment return_list '=' fcn_name - opt_param_list opt_sep opt_list function_end + opt_param_list opt_sep function_body function_end { OCTAVE_YYUSE ($4); OCTAVE_YYUSE ($7); @@ -1748,6 +1776,165 @@ } ; +function_body : at_first_executable_stmt opt_list + { + OCTAVE_YYUSE ($1); + + $$ = $2; + } + | function_body1 opt_sep at_first_executable_stmt opt_list + { + OCTAVE_YYUSE ($2); + + if ($4) + { + for (const auto& elt : *($4)) + $1->append (elt); + } + + $4->clear (); + delete ($4); + + $$ = $1; + } + ; + +at_first_executable_stmt + : // empty + { + $$ = 0; + lexer.m_arguments_is_keyword = false; + } + ; + +function_body1 : arguments_block + { + octave::tree_statement *stmt = parser.make_statement ($1); + + $$ = parser.make_statement_list (stmt); + } + | function_body1 opt_sep arguments_block + { + octave::tree_statement *stmt = parser.make_statement ($3); + + $$ = parser.append_statement_list ($1, $2, stmt, false); + } + ; + +arguments_block : arguments_beg stash_comment opt_sep args_attr_list + args_validation_list opt_sep END + { + OCTAVE_YYUSE ($3); + OCTAVE_YYUSE ($6); + + octave::comment_list *lc = $2; + octave::comment_list *tc = lexer.get_comment (); + + if (! ($$ = parser.make_arguments_block ($1, $4, $5, $7, lc, tc))) + { + // make_arguments_block deleted $4, $5, LC, and TC. + YYABORT; + } + + lexer.m_arguments_is_keyword = true; + } + ; + +arguments_beg : ARGUMENTS + { + $$ = $1; + lexer.m_arguments_is_keyword = false; + } + ; + + +args_attr_list : // empty + { $$ = nullptr; } + | '(' identifier ')' + { + OCTAVE_YYUSE ($1); + OCTAVE_YYUSE ($3); + + // Error if $$ is nullptr. + if (! ($$ = parser.make_args_attribute_list ($2))) + { + // make_args_attribute_list deleted $2. + YYABORT; + } + } + ; + +args_validation_list + : arg_validation + { $$ = parser.make_args_validation_list ($1); } + | args_validation_list sep arg_validation + { + OCTAVE_YYUSE ($2); + + $$ = parser.append_args_validation_list ($1, $3); + } + ; + +arg_validation : identifier size_spec class_name validation_fcns default_value + { + // FIXME: Change grammar to allow IDENTIFIER to be + // be either "NAME" or "NAME '.' NAME". + + if (! ($$ = parser.make_arg_validation ($1, $2, $3, $4, $5))) + { + // make_arg_validation deleted ... + YYABORT; + } + } + ; + +size_spec : // empty + { $$ = nullptr; } + | '(' arg_list ')' + { + OCTAVE_YYUSE ($1); + OCTAVE_YYUSE ($3); + + if (! ($$ = parser.make_arg_size_spec ($2))) + { + // make_arg_size_spec deleted $2. + YYABORT; + } + } + ; + +class_name : // empty + { $$ = nullptr; } + | identifier + { $$ = $1; } + ; + +// Use argument list so we can accept anonymous functions. +validation_fcns : // empty + { $$ = nullptr; } + | '{' arg_list '}' + { + OCTAVE_YYUSE ($1); + OCTAVE_YYUSE ($3); + + if (! ($$ = parser.make_arg_validation_fcns ($2))) + { + // make_arg_validation_fcns deleted $2. + YYABORT; + } + } + ; + +default_value : // empty + { $$ = nullptr; } + | '=' expression + { + OCTAVE_YYUSE ($1); + + $$ = $2; + } + ; + // ======== // Classdef // ======== @@ -3888,6 +4075,90 @@ return retval; } + tree_arguments_block * + base_parser::make_arguments_block (token *arguments_tok, + tree_args_block_attribute_list *attr_list, + tree_args_block_validation_list *validation_list, + token *end_tok, + comment_list *lc, comment_list *tc) + { + tree_arguments_block *retval = nullptr; + + if (end_token_ok (end_tok, token::arguments_end)) + { + filepos beg_pos = arguments_tok->beg_pos (); + + int l = beg_pos.line (); + int c = beg_pos.column (); + + retval = new tree_arguments_block (attr_list, validation_list, l, c); + } + else + { + delete attr_list; + delete validation_list; + + delete lc; + delete tc; + } + + return retval; + } + + tree_arg_validation * + base_parser::make_arg_validation (tree_expression *arg_name, + tree_arg_size_spec *size_spec, + tree_identifier *class_name, + tree_arg_validation_fcns *validation_fcns, + tree_expression *default_value) + { + // FIXME: Validate arguments and convert to more specific types + // (std::string for arg_name and class_name, etc). + + return new tree_arg_validation (arg_name, size_spec, class_name, + validation_fcns, default_value); + } + + tree_args_block_attribute_list * + base_parser::make_args_attribute_list (tree_identifier *attribute_name) + { + // FIXME: Validate argument and convert to more specific type + // (std::string for attribute_name). + + return new tree_args_block_attribute_list (attribute_name); + } + + tree_args_block_validation_list * + base_parser::make_args_validation_list (tree_arg_validation *arg_validation) + { + return new tree_args_block_validation_list (arg_validation); + } + + tree_args_block_validation_list * + base_parser::append_args_validation_list (tree_args_block_validation_list *list, + tree_arg_validation *arg_validation) + { + list->append (arg_validation); + + return list; + } + + tree_arg_size_spec * + base_parser::make_arg_size_spec (tree_argument_list *size_args) + { + // FIXME: Validate argument. + + return new tree_arg_size_spec (size_args); + } + + tree_arg_validation_fcns * + base_parser::make_arg_validation_fcns (tree_argument_list *fcn_args) + { + // FIXME: Validate argument. + + return new tree_arg_validation_fcns (fcn_args); + } + void base_parser::recover_from_parsing_function (void) {
--- a/libinterp/parse-tree/octave.gperf Tue Jun 01 16:57:40 2021 -0400 +++ b/libinterp/parse-tree/octave.gperf Tue Jun 01 13:34:57 2021 -0400 @@ -31,6 +31,7 @@ enum octave_kw_id { + arguments_kw, break_kw, case_kw, catch_kw, @@ -42,6 +43,7 @@ end_kw, end_try_catch_kw, end_unwind_protect_kw, + endarguments_kw, endclassdef_kw, endenumeration_kw, endevents_kw, @@ -84,6 +86,7 @@ struct octave_kw { const char *name; int tok; octave_kw_id kw_id; }; %% +arguments, ARGUMENTS, arguments_kw break, BREAK, break_kw case, CASE, case_kw catch, CATCH, catch_kw @@ -95,6 +98,7 @@ end, END, end_kw end_try_catch, END, end_try_catch_kw end_unwind_protect, END, end_unwind_protect_kw +endarguments, END, endarguments_kw endclassdef, END, endclassdef_kw endenumeration, END, endenumeration_kw endevents, END, endevents_kw
--- a/libinterp/parse-tree/parse.h Tue Jun 01 16:57:40 2021 -0400 +++ b/libinterp/parse-tree/parse.h Tue Jun 01 13:34:57 2021 -0400 @@ -50,7 +50,13 @@ class comment_list; class tree; class tree_anon_fcn_handle; + class tree_arg_size_spec; + class tree_arg_validation; + class tree_arg_validation_fcns; + class tree_args_block_attribute_list; + class tree_args_block_validation_list; class tree_argument_list; + class tree_arguments_block; class tree_array_list; class tree_cell; class tree_classdef; @@ -377,6 +383,41 @@ octave_user_function *fcn, comment_list *lc, int l, int c); + // Make an arguments validation block. + OCTINTERP_API tree_arguments_block * + make_arguments_block (token *arguments_tok, + tree_args_block_attribute_list *attr_list, + tree_args_block_validation_list *validation_list, + token *end_tok, comment_list *lc, comment_list *tc); + + OCTINTERP_API tree_args_block_attribute_list * + make_args_attribute_list (tree_identifier *attribute_name); + + // Make an argument validation. + OCTINTERP_API tree_arg_validation * + make_arg_validation (tree_expression *arg_name, + tree_arg_size_spec *size_spec, + tree_identifier *class_name, + tree_arg_validation_fcns *validation_fcns, + tree_expression *default_value); + + // Make an argument validation list. + OCTINTERP_API tree_args_block_validation_list * + make_args_validation_list (tree_arg_validation *arg_validation); + + // Append an argument validation to an existing list. + OCTINTERP_API tree_args_block_validation_list * + append_args_validation_list (tree_args_block_validation_list *list, + tree_arg_validation *arg_validation); + + // Make an argument size specification object. + OCTINTERP_API tree_arg_size_spec * + make_arg_size_spec (tree_argument_list *size_args); + + // Make a list of argument validation functions. + OCTINTERP_API tree_arg_validation_fcns * + make_arg_validation_fcns (tree_argument_list *fcn_args); + // Reset state after parsing function. OCTINTERP_API void recover_from_parsing_function (void);
--- a/libinterp/parse-tree/pt-all.h Tue Jun 01 16:57:40 2021 -0400 +++ b/libinterp/parse-tree/pt-all.h Tue Jun 01 13:34:57 2021 -0400 @@ -29,6 +29,7 @@ #include "octave-config.h" #include "pt.h" +#include "pt-args-block.h" #include "pt-arg-list.h" #include "pt-assign.h" #include "pt-bp.h"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/parse-tree/pt-args-block.cc Tue Jun 01 13:34:57 2021 -0400 @@ -0,0 +1,43 @@ +//////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2021 The Octave Project Developers +// +// See the file COPYRIGHT.md in the top-level directory of this +// distribution or <https://octave.org/copyright/>. +// +// 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 3 of the License, 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, see +// <https://www.gnu.org/licenses/>. +// +//////////////////////////////////////////////////////////////////////// + +#if defined (HAVE_CONFIG_H) +# include "config.h" +#endif + +#include "pt-args-block.h" + +namespace octave +{ + tree_args_block_validation_list::~tree_args_block_validation_list (void) + { + while (! empty ()) + { + auto p = begin (); + delete *p; + erase (p); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/parse-tree/pt-args-block.h Tue Jun 01 13:34:57 2021 -0400 @@ -0,0 +1,254 @@ +//////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2021 The Octave Project Developers +// +// See the file COPYRIGHT.md in the top-level directory of this +// distribution or <https://octave.org/copyright/>. +// +// 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 3 of the License, 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, see +// <https://www.gnu.org/licenses/>. +// +//////////////////////////////////////////////////////////////////////// + +#if ! defined (octave_pt_args_block_h) +#define octave_pt_args_block_h 1 + +#include "octave-config.h" + +#include "pt-arg-list.h" +#include "pt-cmd.h" +#include "pt-exp.h" +#include "pt-id.h" +#include "pt-walk.h" + +#include "base-list.h" + +namespace octave +{ + class tree_arg_size_spec + { + public: + + tree_arg_size_spec (tree_argument_list *size_args) + : m_size_args (size_args) + { } + + // No copying! + + tree_arg_size_spec (const tree_arg_size_spec&) = delete; + + tree_arg_size_spec& operator = (const tree_arg_size_spec&) = delete; + + ~tree_arg_size_spec (void) + { + delete m_size_args; + } + + void accept (tree_walker& tw) + { + tw.visit_arg_size_spec (*this); + } + + private: + + tree_argument_list *m_size_args; + }; + + class tree_arg_validation_fcns + { + public: + + tree_arg_validation_fcns (tree_argument_list *fcn_args) + : m_fcn_args (fcn_args) + { } + + // No copying! + + tree_arg_validation_fcns (const tree_arg_validation_fcns&) = delete; + + tree_arg_validation_fcns& operator = (const tree_arg_validation_fcns&) = delete; + + ~tree_arg_validation_fcns (void) + { + delete m_fcn_args; + } + + void accept (tree_walker& tw) + { + tw.visit_arg_validation_fcns (*this); + } + + private: + + tree_argument_list *m_fcn_args; + }; + + class tree_arg_validation + { + public: + + tree_arg_validation (tree_expression *arg_name, + tree_arg_size_spec *size_spec, + tree_identifier *class_name, + tree_arg_validation_fcns *validation_fcns, + tree_expression *default_value) + : m_arg_name (arg_name), m_size_spec (size_spec), + m_class_name (class_name), m_validation_fcns (validation_fcns), + m_default_value (default_value) + { } + + // No copying! + + tree_arg_validation (const tree_arg_validation&) = delete; + + tree_arg_validation& operator = (const tree_arg_validation&) = delete; + + ~tree_arg_validation (void) + { + delete m_arg_name; + delete m_size_spec; + delete m_class_name; + delete m_validation_fcns; + delete m_default_value; + } + + void accept (tree_walker& tw) + { + tw.visit_arg_validation (*this); + } + + private: + + // May be a simple identifier or an identifier followed by a single + // field name. + tree_expression *m_arg_name; + tree_arg_size_spec *m_size_spec; + tree_identifier *m_class_name; + tree_arg_validation_fcns *m_validation_fcns; + tree_expression *m_default_value; + }; + + class tree_args_block_validation_list : public base_list<tree_arg_validation *> + { + public: + + tree_args_block_validation_list (void) { } + + tree_args_block_validation_list (tree_arg_validation *a) { append (a); } + + tree_args_block_validation_list (const base_list<tree_arg_validation *>& a) + : base_list<tree_arg_validation *> (a) + { } + + // No copying! + + tree_args_block_validation_list (const tree_args_block_validation_list&) = delete; + + tree_args_block_validation_list& operator = (const tree_args_block_validation_list&) = delete; + + ~tree_args_block_validation_list (void); + + void accept (tree_walker& tw) + { + tw.visit_args_block_validation_list (*this); + } + }; + + // FIXME: Maybe make this object an actual list even though we don't + // currently need it? + + class tree_args_block_attribute_list + { + public: + + tree_args_block_attribute_list (tree_identifier *id = nullptr) + : m_id (id) + { } + + // No copying! + + tree_args_block_attribute_list (const tree_args_block_attribute_list&) = delete; + + tree_args_block_attribute_list& operator = (const tree_args_block_attribute_list&) = delete; + + ~tree_args_block_attribute_list (void) + { + delete m_id; + } + + void accept (tree_walker& tw) + { + tw.visit_args_block_attribute_list (*this); + } + + private: + + tree_identifier *m_id; + }; + + // Arguments block. + + class tree_arguments_block : public tree_command + { + public: + + tree_arguments_block (tree_args_block_attribute_list *attr_list, + tree_args_block_validation_list *validation_list, + int l = -1, int c = -1) + : tree_command (l, c), m_attr_list (attr_list), + m_validation_list (validation_list), + m_lead_comm (nullptr), m_trail_comm (nullptr) + { } + + // No copying! + + tree_arguments_block (const tree_arguments_block&) = delete; + + tree_arguments_block& operator = (const tree_arguments_block&) = delete; + + ~tree_arguments_block (void) + { + delete m_attr_list; + delete m_validation_list; + + delete m_lead_comm; + delete m_trail_comm; + } + + comment_list * leading_comment (void) { return m_lead_comm; } + + comment_list * trailing_comment (void) { return m_trail_comm; } + + void accept (tree_walker& tw) + { + tw.visit_arguments_block (*this); + } + + private: + + tree_args_block_attribute_list *m_attr_list; + + tree_args_block_validation_list *m_validation_list; + + // Comment preceding ARGUMENTS token. + comment_list *m_lead_comm; + + // Comment preceding ENDARGUMENTS token. + comment_list *m_trail_comm; + }; +} + +#endif
--- a/libinterp/parse-tree/pt-bp.cc Tue Jun 01 16:57:40 2021 -0400 +++ b/libinterp/parse-tree/pt-bp.cc Tue Jun 01 13:34:57 2021 -0400 @@ -73,6 +73,42 @@ } void + tree_breakpoint::visit_arguments_block (tree_arguments_block&) + { + // FIXME + } + + void + tree_breakpoint::visit_args_block_attribute_list (tree_args_block_attribute_list&) + { + panic_impossible (); + } + + void + tree_breakpoint::visit_args_block_validation_list (tree_args_block_validation_list&) + { + panic_impossible (); + } + + void + tree_breakpoint::visit_arg_validation (tree_arg_validation&) + { + panic_impossible (); + } + + void + tree_breakpoint::visit_arg_size_spec (tree_arg_size_spec&) + { + panic_impossible (); + } + + void + tree_breakpoint::visit_arg_validation_fcns (tree_arg_validation_fcns&) + { + panic_impossible (); + } + + void tree_breakpoint::visit_binary_expression (tree_binary_expression&) { panic_impossible ();
--- a/libinterp/parse-tree/pt-bp.h Tue Jun 01 16:57:40 2021 -0400 +++ b/libinterp/parse-tree/pt-bp.h Tue Jun 01 13:34:57 2021 -0400 @@ -62,6 +62,18 @@ void visit_argument_list (tree_argument_list&); + void visit_arguments_block (tree_arguments_block&); + + void visit_args_block_attribute_list (tree_args_block_attribute_list&); + + void visit_args_block_validation_list (tree_args_block_validation_list&); + + void visit_arg_validation (tree_arg_validation&); + + void visit_arg_size_spec (tree_arg_size_spec&); + + void visit_arg_validation_fcns (tree_arg_validation_fcns&); + void visit_binary_expression (tree_binary_expression&); void visit_break_command (tree_break_command&);
--- a/libinterp/parse-tree/pt-eval.cc Tue Jun 01 16:57:40 2021 -0400 +++ b/libinterp/parse-tree/pt-eval.cc Tue Jun 01 13:34:57 2021 -0400 @@ -1245,6 +1245,42 @@ } void + tree_evaluator::visit_arguments_block (tree_arguments_block&) + { + warning ("function arguments validation blocks are not supported"); + } + + void + tree_evaluator::visit_args_block_attribute_list (tree_args_block_attribute_list&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_args_block_validation_list (tree_args_block_validation_list&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_arg_validation (tree_arg_validation&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_arg_size_spec (tree_arg_size_spec&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_arg_validation_fcns (tree_arg_validation_fcns&) + { + panic_impossible (); + } + + void tree_evaluator::visit_binary_expression (tree_binary_expression&) { panic_impossible ();
--- a/libinterp/parse-tree/pt-eval.h Tue Jun 01 16:57:40 2021 -0400 +++ b/libinterp/parse-tree/pt-eval.h Tue Jun 01 13:34:57 2021 -0400 @@ -212,6 +212,18 @@ void visit_argument_list (tree_argument_list&); + void visit_arguments_block (tree_arguments_block&); + + void visit_args_block_attribute_list (tree_args_block_attribute_list&); + + void visit_args_block_validation_list (tree_args_block_validation_list&); + + void visit_arg_validation (tree_arg_validation&); + + void visit_arg_size_spec (tree_arg_size_spec&); + + void visit_arg_validation_fcns (tree_arg_validation_fcns&); + void visit_binary_expression (tree_binary_expression&); void visit_boolean_expression (tree_boolean_expression&);
--- a/libinterp/parse-tree/pt-pr-code.cc Tue Jun 01 16:57:40 2021 -0400 +++ b/libinterp/parse-tree/pt-pr-code.cc Tue Jun 01 13:34:57 2021 -0400 @@ -76,6 +76,45 @@ } void + tree_print_code::visit_arguments_block (tree_arguments_block&) + { + indent (); + + // FIXME + m_os << "arguments ... endarguments"; + } + + void + tree_print_code::visit_args_block_attribute_list (tree_args_block_attribute_list&) + { + panic_impossible (); + } + + void + tree_print_code::visit_args_block_validation_list (tree_args_block_validation_list&) + { + panic_impossible (); + } + + void + tree_print_code::visit_arg_validation (tree_arg_validation&) + { + panic_impossible (); + } + + void + tree_print_code::visit_arg_size_spec (tree_arg_size_spec&) + { + panic_impossible (); + } + + void + tree_print_code::visit_arg_validation_fcns (tree_arg_validation_fcns&) + { + panic_impossible (); + } + + void tree_print_code::visit_binary_expression (tree_binary_expression& expr) { indent ();
--- a/libinterp/parse-tree/pt-pr-code.h Tue Jun 01 16:57:40 2021 -0400 +++ b/libinterp/parse-tree/pt-pr-code.h Tue Jun 01 13:34:57 2021 -0400 @@ -70,6 +70,18 @@ void visit_argument_list (tree_argument_list&); + void visit_arguments_block (tree_arguments_block&); + + void visit_args_block_attribute_list (tree_args_block_attribute_list&); + + void visit_args_block_validation_list (tree_args_block_validation_list&); + + void visit_arg_validation (tree_arg_validation&); + + void visit_arg_size_spec (tree_arg_size_spec&); + + void visit_arg_validation_fcns (tree_arg_validation_fcns&); + void visit_binary_expression (tree_binary_expression&); void visit_break_command (tree_break_command&);
--- a/libinterp/parse-tree/pt-walk.cc Tue Jun 01 16:57:40 2021 -0400 +++ b/libinterp/parse-tree/pt-walk.cc Tue Jun 01 13:34:57 2021 -0400 @@ -49,6 +49,36 @@ } } + void tree_walker::visit_arguments_block (tree_arguments_block&) + { + // FIXME? + } + + void tree_walker::visit_args_block_attribute_list (tree_args_block_attribute_list&) + { + // FIXME? + } + + void tree_walker::visit_args_block_validation_list (tree_args_block_validation_list&) + { + // FIXME? + } + + void tree_walker::visit_arg_validation (tree_arg_validation&) + { + // FIXME? + } + + void tree_walker::visit_arg_size_spec (tree_arg_size_spec&) + { + // FIXME? + } + + void tree_walker::visit_arg_validation_fcns (tree_arg_validation_fcns&) + { + // FIXME? + } + void tree_walker::visit_binary_expression (tree_binary_expression& expr) { tree_expression *op1 = expr.lhs ();
--- a/libinterp/parse-tree/pt-walk.h Tue Jun 01 16:57:40 2021 -0400 +++ b/libinterp/parse-tree/pt-walk.h Tue Jun 01 13:34:57 2021 -0400 @@ -41,7 +41,13 @@ // class tree_black_hole class tree_anon_fcn_handle; + class tree_arg_size_spec; + class tree_arg_validation; + class tree_arg_validation_fcns; + class tree_args_block_attribute_list; + class tree_args_block_validation_list; class tree_argument_list; + class tree_arguments_block; class tree_binary_expression; class tree_boolean_expression; class tree_compound_binary_expression; @@ -121,6 +127,18 @@ virtual void visit_argument_list (tree_argument_list&); + virtual void visit_arguments_block (tree_arguments_block&); + + virtual void visit_args_block_attribute_list (tree_args_block_attribute_list&); + + virtual void visit_args_block_validation_list (tree_args_block_validation_list&); + + virtual void visit_arg_validation (tree_arg_validation&); + + virtual void visit_arg_size_spec (tree_arg_size_spec&); + + virtual void visit_arg_validation_fcns (tree_arg_validation_fcns&); + virtual void visit_binary_expression (tree_binary_expression&); virtual void visit_boolean_expression (tree_boolean_expression&);