Mercurial > octave
comparison libinterp/parse-tree/pt-eval.cc @ 30919:4ed7dfe28584
move eval of anon fcn handles and built-in and mex functions to pt-eval.cc
For consistency with the evaluation of user-defined functions and
scripts, move the evaluation of anonymous function handles and
built-in and mex functions to the tree_evaluator class in pt-eval.cc.
* pt-eval.h, pt-eval.cc (tree_evaluator::evaluate_anon_fcn_handle,
tree_evaluator::execute_builtin_function,
tree_evaluator::execute_mex_function): New functions extracted
from tree_anon_fcn_handle::evalueate, octave_builtin::execute and
octave_mex_function::execute, respectively.
* ov-builtin.cc (octave_builtin::execute):
Forward to tree_evaluator::execute_builtin_function.
* ov-mex-fcn.cc (octave_mex_function::execute):
Forward to tree_evaluator::execute_mex_function.
* pt-fcn-handle.cc (tree_anon_fcn_handle::evaluate):
Forward to tree_evaluator::evaluate_anon_fcn_handle.
* mex.cc: Move call_mex inside octave namespace.
* mex-private.h: New file.
* libinterp/corefcn/module.mk: Update.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Fri, 08 Apr 2022 14:11:05 -0400 |
parents | c9788d7f6e65 |
children | 344e1152ed88 e88a07dec498 |
comparison
equal
deleted
inserted
replaced
30918:297f32524dd8 | 30919:4ed7dfe28584 |
---|---|
51 #include "errwarn.h" | 51 #include "errwarn.h" |
52 #include "event-manager.h" | 52 #include "event-manager.h" |
53 #include "input.h" | 53 #include "input.h" |
54 #include "interpreter-private.h" | 54 #include "interpreter-private.h" |
55 #include "interpreter.h" | 55 #include "interpreter.h" |
56 #include "mex-private.h" | |
56 #include "octave.h" | 57 #include "octave.h" |
57 #include "ov-classdef.h" | 58 #include "ov-classdef.h" |
58 #include "ov-fcn-handle.h" | 59 #include "ov-fcn-handle.h" |
60 #include "ov-mex-fcn.h" | |
59 #include "ov-usr-fcn.h" | 61 #include "ov-usr-fcn.h" |
60 #include "ov-re-sparse.h" | 62 #include "ov-re-sparse.h" |
61 #include "ov-cx-sparse.h" | 63 #include "ov-cx-sparse.h" |
62 #include "parse.h" | 64 #include "parse.h" |
63 #include "profiler.h" | 65 #include "profiler.h" |
3321 | 3323 |
3322 if (body) | 3324 if (body) |
3323 body->accept (*this); | 3325 body->accept (*this); |
3324 } | 3326 } |
3325 | 3327 |
3326 void | 3328 octave_value |
3327 tree_evaluator::visit_octave_user_script (octave_user_script&) | 3329 tree_evaluator::evaluate_anon_fcn_handle (tree_anon_fcn_handle& afh) |
3328 { | 3330 { |
3329 // ?? | 3331 // FIXME: should CMD_LIST be limited to a single expression? |
3330 panic_impossible (); | 3332 // I think that is what Matlab does. |
3333 | |
3334 symbol_scope new_scope; | |
3335 symbol_scope scope = afh.scope (); | |
3336 if (scope) | |
3337 new_scope = scope.dup (); | |
3338 | |
3339 tree_parameter_list *param_list = afh.parameter_list (); | |
3340 tree_parameter_list *param_list_dup | |
3341 = param_list ? param_list->dup (new_scope) : nullptr; | |
3342 | |
3343 tree_parameter_list *ret_list = nullptr; | |
3344 | |
3345 tree_statement_list *stmt_list = nullptr; | |
3346 | |
3347 symbol_scope parent_scope = get_current_scope (); | |
3348 | |
3349 new_scope.set_parent (parent_scope); | |
3350 new_scope.set_primary_parent (parent_scope); | |
3351 | |
3352 tree_expression *expr = afh.expression (); | |
3353 if (expr) | |
3354 { | |
3355 tree_expression *expr_dup = expr->dup (new_scope); | |
3356 tree_statement *stmt = new tree_statement (expr_dup, nullptr); | |
3357 stmt_list = new tree_statement_list (stmt); | |
3358 } | |
3359 | |
3360 tree_anon_scopes anon_fcn_ctx (afh); | |
3361 | |
3362 std::set<std::string> free_vars = anon_fcn_ctx.free_variables (); | |
3363 | |
3364 stack_frame::local_vars_map local_vars; | |
3365 | |
3366 std::shared_ptr<stack_frame> frame | |
3367 = m_call_stack.get_current_stack_frame (); | |
3368 | |
3369 for (auto& name : free_vars) | |
3370 { | |
3371 octave_value val = frame->varval (name); | |
3372 | |
3373 if (val.is_defined ()) | |
3374 local_vars[name] = val; | |
3375 } | |
3376 | |
3377 octave_user_function *af | |
3378 = new octave_user_function (new_scope, param_list_dup, ret_list, | |
3379 stmt_list); | |
3380 | |
3381 octave_function *curr_fcn = m_call_stack.current_function (); | |
3382 | |
3383 bool is_nested = false; | |
3384 | |
3385 if (curr_fcn) | |
3386 { | |
3387 // FIXME: maybe it would be better to just stash curr_fcn | |
3388 // instead of individual bits of info about it? | |
3389 | |
3390 // An anonymous function defined inside another nested function | |
3391 // or parent of a nested function also behaves like a nested | |
3392 // function. | |
3393 | |
3394 if (curr_fcn->is_parent_function () || curr_fcn->is_nested_function ()) | |
3395 { | |
3396 is_nested = true; | |
3397 af->mark_as_nested_function (); | |
3398 new_scope.set_nesting_depth (parent_scope.nesting_depth () + 1); | |
3399 } | |
3400 | |
3401 af->stash_dir_name (curr_fcn->dir_name ()); | |
3402 | |
3403 new_scope.cache_fcn_file_name (curr_fcn->fcn_file_name ()); | |
3404 new_scope.cache_dir_name (curr_fcn->dir_name ()); | |
3405 | |
3406 // The following is needed so that class method dispatch works | |
3407 // properly for anonymous functions that wrap class methods. | |
3408 | |
3409 if (curr_fcn->is_class_method () || curr_fcn->is_class_constructor ()) | |
3410 af->stash_dispatch_class (curr_fcn->dispatch_class ()); | |
3411 | |
3412 af->stash_fcn_file_name (curr_fcn->fcn_file_name ()); | |
3413 } | |
3414 | |
3415 af->mark_as_anonymous_function (); | |
3416 | |
3417 octave_value ov_fcn (af); | |
3418 | |
3419 return (is_nested | |
3420 ? octave_value (new octave_fcn_handle (ov_fcn, local_vars, frame)) | |
3421 : octave_value (new octave_fcn_handle (ov_fcn, local_vars))); | |
3422 } | |
3423 | |
3424 octave_value_list | |
3425 tree_evaluator::execute_builtin_function (octave_builtin& builtin_function, | |
3426 int nargout, | |
3427 const octave_value_list& args) | |
3428 { | |
3429 octave_value_list retval; | |
3430 | |
3431 if (args.has_magic_colon ()) | |
3432 error ("invalid use of colon in function argument list"); | |
3433 | |
3434 profiler::enter<octave_builtin> block (m_profiler, builtin_function); | |
3435 | |
3436 octave_builtin::fcn fcn = builtin_function.function (); | |
3437 | |
3438 if (fcn) | |
3439 retval = (*fcn) (args, nargout); | |
3440 else | |
3441 { | |
3442 octave_builtin::meth meth = builtin_function.method (); | |
3443 | |
3444 retval = (*meth) (m_interpreter, args, nargout); | |
3445 } | |
3446 | |
3447 // Do not allow null values to be returned from functions. | |
3448 // FIXME: perhaps true builtins should be allowed? | |
3449 | |
3450 retval.make_storable_values (); | |
3451 | |
3452 // Fix the case of a single undefined value. | |
3453 // This happens when a compiled function uses | |
3454 // | |
3455 // octave_value retval; | |
3456 // | |
3457 // instead of | |
3458 // | |
3459 // octave_value_list retval; | |
3460 // | |
3461 // the idiom is very common, so we solve that here. | |
3462 | |
3463 if (retval.length () == 1 && retval.xelem (0).is_undefined ()) | |
3464 retval.clear (); | |
3465 | |
3466 return retval; | |
3467 } | |
3468 | |
3469 octave_value_list | |
3470 tree_evaluator::execute_mex_function (octave_mex_function& mex_function, | |
3471 int nargout, | |
3472 const octave_value_list& args) | |
3473 { | |
3474 octave_value_list retval; | |
3475 | |
3476 if (args.has_magic_colon ()) | |
3477 error ("invalid use of colon in function argument list"); | |
3478 | |
3479 profiler::enter<octave_mex_function> block (m_profiler, mex_function); | |
3480 | |
3481 retval = call_mex (mex_function, args, nargout); | |
3482 | |
3483 return retval; | |
3331 } | 3484 } |
3332 | 3485 |
3333 octave_value_list | 3486 octave_value_list |
3334 tree_evaluator::execute_user_script (octave_user_script& user_script, | 3487 tree_evaluator::execute_user_script (octave_user_script& user_script, |
3335 int nargout, | 3488 int nargout, |
3372 | 3525 |
3373 return retval; | 3526 return retval; |
3374 } | 3527 } |
3375 | 3528 |
3376 void | 3529 void |
3377 tree_evaluator::visit_octave_user_function (octave_user_function&) | 3530 tree_evaluator::visit_octave_user_script (octave_user_script&) |
3378 { | 3531 { |
3379 // ?? | 3532 // ?? |
3380 panic_impossible (); | 3533 panic_impossible (); |
3381 } | 3534 } |
3382 | 3535 |
3535 ignored_outputs, | 3688 ignored_outputs, |
3536 varargout); | 3689 varargout); |
3537 } | 3690 } |
3538 | 3691 |
3539 return retval; | 3692 return retval; |
3693 } | |
3694 | |
3695 void | |
3696 tree_evaluator::visit_octave_user_function (octave_user_function&) | |
3697 { | |
3698 // ?? | |
3699 panic_impossible (); | |
3540 } | 3700 } |
3541 | 3701 |
3542 void | 3702 void |
3543 tree_evaluator::visit_octave_user_function_header (octave_user_function&) | 3703 tree_evaluator::visit_octave_user_function_header (octave_user_function&) |
3544 { | 3704 { |