Mercurial > octave-libgccjit
diff src/oct-parse.yy @ 14544:be18c9e359bf
Nested function support (bug #35772)
* src/oct-parse.yy (push_fcn_symtab, recover_from_parsing_function)
(eval_string): Keep track of a stack of nested functions.
(parse_fcn_file): Keep track of a stack of nested functions and remove
warning that nested functions are not supported.
(frob_function): Call symbol_table::install_nestfunction for nested functions.
(finish_function): Call symbol_table::update_nest on top level functions.
* src/ov-fcn-handle.cc (octave_fcn_handle::octave_fcn_handle):
Error when creating a handle to a nested function.
* src/ov-usr-fcn.cc (octave_user_function::octave_user_function):
Initialize new members.
(octave_user_function::do_multi_index_op): Use active_context to
determine execution context.
* src/ov-usr-fcn.h (octave_user_function::active_context,
octave_user_function::is_nested_function,
octave_user_function::mark_as_nested_function): New functions.
* src/pt-id.h (symbol_table::xsym): Check symbol validity.
* src/symtab.cc (symbol_table::symbol_record::symbol_record_rep::active_context,
symbol_table::install_nestfunction, symbol_table::do_update_nest):
New functions.
(symbol_table::symbol_record::symbol_record_rep::dump): Use varval ()
instead of varval (current_context).
(symbol_table::fcn_info::fcn_info_rep::xfind,
symbol_table::fcn_info::fcn_info_rep::x_builtin_find): Allow for
parents of parents in subfunction search.
* src/symtab.h (symbol_table::symbol_record::symbol_record_rep::symbol_record_rep,
symbol_table::symbol_record::symbol_record): New parameter,
decl_scope.
(symbol_table::symbol_record::symbol_record_rep::force_variable,
symbol_table::symbol_record::force_variable,
symbol_table::symbol_record::symbol_record_rep::varref,
symbol_table::symbol_record::varref,
symbol_table::symbol_record::symbol_record_rep::varval,
symbol_table::symbol_record::varval,
symbol_table::symbol_record::symbol_record_rep::is_defined,
symbol_table::symbol_record::is_defined,
symbol_table::symbol_record::symbol_record_rep::is_variable,
symbol_table::symbol_record::is_variable,
symbol_table::symbol_record::varval,
symbol_table::symbol_record::symbol_record_rep::varval): Use xdefault_context.
symbol_table::symbol_record::symbol_record_rep::push_context,
symbol_table::symbol_record::push_context,
symbol_table::symbol_record::symbol_record_rep::pop_context,
symbol_table::symbol_record::pop_context,
symbol_table::symbol_record::symbol_record_rep::clear,
symbol_table::symbol_record::clear): Only work when the decl_scope of
the symbol is the active scope.
(symbol_table::symbol_record::symbol_record_rep::is_valid,
symbol_table::symbol_record::is_valid,
symbol_table::symbol_record::symbol_record_rep::invalidate,
symbol_table::symbol_record::invalidate,
symbol_table::symbol_record::symbol_record_rep::set_curr_fcn,
symbol_table::symbol_record::set_curr_fcn,
symbol_table::symbol_record::symbol_record_rep::scope,
symbol_table::symbol_record::scope,
symbol_table::symbol_record::active_context,
symbol_table::update_nest, symbol_table::symbol_table,
symbol_table::add_nest_child, symbol_table::look_nonlocal): New functions.
(symbol_table::symbol_record::symbol_record_rep::init_persistent):
Init to xdefault_context instead of xcurrent_context.
(symbol_table::symbol_record::symbol_record_rep::dup,
symbol_table::symbol_record::dup): New parameter, scope.
(symbol_table::set_scope, symbol_table::dup_scope,
symbol_table:;get_instance): Pass scope_id to symbol_table constructor.
(symbol_table::find_symbol, symbol_table::glob_global_variables,
symbol_table::regexp_global_variables): Specify scope when creating
symbol_record.
(symbol_table::force_variable, symbol_table::varref,
symbol_table::varval, symbol_table::all_variables): Default to
xdefault_context instead of xcurrent_context.
(symbol_table::do_dup_scope): Pass scope of new symbol table to symbol
dup.
(symbol_table::do_insert): Check nest_parent for nonlocals.
(symbol_table::do_push_context, symbol_table::do_pop_context,
symbol_table::do_clear_variables, symbol_table::do_clear_objects,
symbol_table::do_clear_variable, symbol_table::do_clear_variable_pattern,
symbol_table::do_clear_variable_regexp): Pass my_scope to symbol.
* test/Makefile.am: Include nest/module.mk.
* test/nest/arg_nest.m: New file.
* test/nest/arg_ret.m: New file.
* test/nest/module.mk: New file.
* test/nest/no_closure.m: New file.
* test/nest/persistent_nest.m: New file.
* test/nest/recursive_nest.m: New file.
* test/nest/recursive_nest2.m: New file.
* test/nest/recursive_nest3.m: New file.
* test/nest/scope0.m: New file.
* test/nest/scope1.m: New file.
* test/nest/scope2.m: New file.
* test/nest/scope3.m: New file.
* test/nest/script_nest.m: New file.
* test/nest/script_nest_script.m: New file.
* test/nest/test_nest.m: New file.
* test/nest/varg_nest.m: New file.
* test/nest/varg_nest2.m: New file.
author | Max Brister <max@2bass.com> |
---|---|
date | Tue, 10 Apr 2012 20:42:22 -0400 |
parents | e6aa044253eb |
children | 3a10d5bdada8 |
line wrap: on
line diff
--- a/src/oct-parse.yy Tue Apr 10 17:14:24 2012 -0400 +++ b/src/oct-parse.yy Tue Apr 10 20:42:22 2012 -0400 @@ -115,6 +115,11 @@ // nested function. static int current_function_depth = 0; +// A stack holding the nested function scopes being parsed. +// We don't use std::stack, because we want the clear method. Also, we +// must access one from the top +static std::vector<symbol_table::scope_id> function_scopes; + // Maximum function depth detected. Just here to determine whether // we have nested functions or just implicitly ended subfunctions. static int max_function_depth = 0; @@ -1226,6 +1231,8 @@ symbol_table::set_scope (symbol_table::alloc_scope ()); + function_scopes.push_back (symbol_table::current_scope ()); + if (! reading_script_file && current_function_depth == 1 && ! parsing_subfunctions) primary_fcn_scope = symbol_table::current_scope (); @@ -2867,7 +2874,11 @@ if (current_function_depth > 1 || parsing_subfunctions) { fcn->stash_parent_fcn_name (curr_fcn_file_name); - fcn->stash_parent_fcn_scope (primary_fcn_scope); + + if (current_function_depth > 1) + fcn->stash_parent_fcn_scope (function_scopes[function_scopes.size()-2]); + else + fcn->stash_parent_fcn_scope (primary_fcn_scope); } if (lexer_flags.parsing_class_method) @@ -2943,10 +2954,22 @@ { fcn->mark_as_subfunction (); - symbol_table::install_subfunction (nm, octave_value (fcn), - primary_fcn_scope); + if (endfunction_found && function_scopes.size () > 1) + { + symbol_table::scope_id pscope + = function_scopes[function_scopes.size()-2]; + + symbol_table::install_nestfunction (nm, octave_value (fcn), + pscope); + } + else + symbol_table::install_subfunction (nm, octave_value (fcn), + primary_fcn_scope); } + if (current_function_depth == 1 && fcn) + symbol_table::update_nest (fcn->scope ()); + if (! reading_fcn_file && current_function_depth == 1) { // We are either reading a script file or defining a function @@ -2985,6 +3008,7 @@ parsing_subfunctions = true; current_function_depth--; + function_scopes.pop_back (); lexer_flags.defining_func--; lexer_flags.parsed_function_name.pop (); @@ -3454,6 +3478,7 @@ frame.protect_var (line_editing); frame.protect_var (current_class_name); frame.protect_var (current_function_depth); + frame.protect_var (function_scopes); frame.protect_var (max_function_depth); frame.protect_var (parsing_subfunctions); frame.protect_var (endfunction_found); @@ -3464,6 +3489,7 @@ line_editing = false; current_class_name = dispatch_type; current_function_depth = 0; + function_scopes.clear (); max_function_depth = 0; parsing_subfunctions = false; endfunction_found = false; @@ -3582,11 +3608,6 @@ if (status != 0) error ("parse error while reading %s file %s", file_type.c_str(), ff.c_str ()); - else if (reading_fcn_file && endfunction_found - && max_function_depth > 1) - warning_with_id ("Octave:nested-functions-coerced", - "nested functions are coerced into subfunctions " - "in file %s", ff.c_str ()); } else { @@ -4298,6 +4319,7 @@ frame.protect_var (line_editing); frame.protect_var (current_eval_string); frame.protect_var (current_function_depth); + frame.protect_var (function_scopes); frame.protect_var (max_function_depth); frame.protect_var (parsing_subfunctions); frame.protect_var (endfunction_found); @@ -4312,6 +4334,7 @@ parser_end_of_input = false; line_editing = false; current_function_depth = 0; + function_scopes.clear (); max_function_depth = 0; parsing_subfunctions = false; endfunction_found = false;