Mercurial > octave
changeset 33573:1cfa8b20a07d bytecode-interpreter
maint: Merge default to bytecode-interpreter
author | Arun Giridhar <arungiridhar@gmail.com> |
---|---|
date | Sat, 11 May 2024 15:03:00 -0400 |
parents | 9f0f7a898b73 (current diff) c0d79d64a1b8 (diff) |
children | e894b4443965 |
files | etc/NEWS.9.md libinterp/parse-tree/pt-eval.cc |
diffstat | 10 files changed, 251 insertions(+), 23 deletions(-) [+] |
line wrap: on
line diff
--- a/etc/NEWS.10.md Fri May 10 17:57:29 2024 -0400 +++ b/etc/NEWS.10.md Sat May 11 15:03:00 2024 -0400 @@ -31,6 +31,9 @@ - The third output for `unique` is now correct when `stable` sort option is used. +- Support setting breakpoints in `set` or `get` methods of `classdef` + properties (bug #65610). + ### Graphical User Interface ### Graphics backend
--- a/etc/NEWS.9.md Fri May 10 17:57:29 2024 -0400 +++ b/etc/NEWS.9.md Sat May 11 15:03:00 2024 -0400 @@ -19,6 +19,13 @@ states (bug #65595). - Fix segmentation fault when trying to set breakpoint in non-existent method of `classdef` class (bug #65610). +- Improve default display of `classdef` properties (bug #62432). +- Avoid crash with Qt6 6.7.0 (bug #65605). +- `bar.m`: Catch input number validation error. +- Prevent OOM crash or segmentation fault in `sort ()` when `dim` equals `Inf` + (bug #65712). +- `legend.m`: Avoid setting more colors than coordinates for `patch` objects + (bug #65632). ### GUI @@ -44,6 +51,10 @@ summary. - Run test program for polymorphic allocators if possible instead of a simple build check. +- Speed up BIST for the central part of `convn` with `'full'` shape. +- Require Qt Widgets module when building the GUI (bug #65625). +- `bug-53027.tst`: Delete temporary file after test is done (bug #53027). +- Avoid build error with GCC 14 when targeting Windows. ### Documentation @@ -56,6 +67,12 @@ - Add application notes in `fminsearch`, `fminbnd`, `fminunc` indicating the preferred way to pass parameters is through anonymous functions. - Update remaining copyright statements to 2024. +- Minor fix for `setappdata.m`. +- Section "Assignment Expressions": Use `@emph` rather than `@i` macro for + better rendering in plaintext formats. +- Section "Running Octave": Tell new users how to start Octave on their + computers. +- `tsearch`: Add programming note about expected performance. ### Deprecated functions, properties, and operators
--- a/libinterp/corefcn/xnorm.cc Fri May 10 17:57:29 2024 -0400 +++ b/libinterp/corefcn/xnorm.cc Sat May 11 15:03:00 2024 -0400 @@ -51,7 +51,7 @@ retval = octave_value (0); else if (isvector) { - if (isfloat & iscomplex) + if (isfloat && iscomplex) retval = octave::xnorm (x.float_complex_column_vector_value (), p.float_value ()); else if (isfloat) @@ -75,7 +75,7 @@ } else { - if (isfloat & iscomplex) + if (isfloat && iscomplex) retval = octave::xnorm (x.float_complex_matrix_value (), p.float_value ()); else if (isfloat) @@ -115,7 +115,7 @@ } else { - if (isfloat & iscomplex) + if (isfloat && iscomplex) retval = octave::xcolnorms (x.float_complex_matrix_value (), p.float_value ()); else if (isfloat) @@ -155,7 +155,7 @@ } else { - if (isfloat & iscomplex) + if (isfloat && iscomplex) retval = octave::xrownorms (x.float_complex_matrix_value (), p.float_value ()); else if (isfloat) @@ -193,7 +193,7 @@ } else { - if (isfloat & iscomplex) + if (isfloat && iscomplex) retval = octave::xfrobnorm (x.float_complex_matrix_value ()); else if (isfloat) retval = octave::xfrobnorm (x.float_matrix_value ());
--- a/libinterp/octave-value/cdef-class.cc Fri May 10 17:57:29 2024 -0400 +++ b/libinterp/octave-value/cdef-class.cc Sat May 11 15:03:00 2024 -0400 @@ -721,27 +721,73 @@ const octave_value& fcn = i->second.get_function (); octave_user_code *user_code = fcn.user_code_value (); - if (user_code == nullptr) + if (! user_code) continue; - octave_user_function* pfcn - = dynamic_cast<octave_user_function*> (user_code); + octave_user_function *pfcn + = dynamic_cast<octave_user_function *> (user_code); - if (pfcn == nullptr) + if (! pfcn) continue; octave::filepos end_pos = pfcn->end_pos (); int end_line = end_pos.line (); - if (line <= end_line && end_line <= closest_match_end_line && pfcn->is_defined () - && pfcn->is_user_code ()) + if (line <= end_line && end_line <= closest_match_end_line + && pfcn->is_defined () && pfcn->is_user_code ()) { closest_match = fcn; closest_match_end_line = end_line; } } + // repeat the same for set and get methods of properties + for (auto i = m_property_map.cbegin (); i != m_property_map.cend (); ++i) + { + const octave_value& get_meth = i->second.get ("GetMethod"); + if (get_meth.is_function_handle ()) + { + octave_user_function *pfcn + = get_meth.user_function_value (); + + if (! pfcn) + continue; + + octave::filepos end_pos = pfcn->end_pos (); + + int end_line = end_pos.line (); + + if (line <= end_line && end_line <= closest_match_end_line + && pfcn->is_defined () && pfcn->is_user_code ()) + { + closest_match = get_meth; + closest_match_end_line = end_line; + } + } + + const octave_value& set_meth = i->second.get ("SetMethod"); + if (set_meth.is_function_handle ()) + { + octave_user_function *pfcn + = set_meth.user_function_value (); + + if (! pfcn) + continue; + + octave::filepos end_pos = pfcn->end_pos (); + + int end_line = end_pos.line (); + + if (line <= end_line && end_line <= closest_match_end_line + && pfcn->is_defined () && pfcn->is_user_code ()) + { + closest_match = set_meth; + closest_match_end_line = end_line; + } + } + } + return closest_match; }
--- a/libinterp/parse-tree/bp-table.cc Fri May 10 17:57:29 2024 -0400 +++ b/libinterp/parse-tree/bp-table.cc Sat May 11 15:03:00 2024 -0400 @@ -800,7 +800,11 @@ if (line < 0) return nullptr; - return m_cls.get_method (line).user_code_value (true); + octave_value method = m_cls.get_method (line); + if (method.is_function_handle ()) + return method.user_function_value ()->user_code_value (true); + else + return method.user_code_value (true); } bool is_function () const { return m_fcn; } @@ -847,6 +851,31 @@ if (fcn != nullptr) m_methods_cache.push_back (fcn); } + + + // Check get and set methods of properties + const std::map<std::string, cdef_property>& prop_map + = m_cls.get_property_map (cdef_class::property_all); + for (auto iter = prop_map.cbegin (); iter != prop_map.cend (); ++iter) + { + octave_value get_meth = iter->second.get ("GetMethod"); + if (get_meth.is_function_handle ()) + { + octave_user_code *fcn + = get_meth.user_function_value ()->user_code_value (true); + if (fcn != nullptr) + m_methods_cache.push_back (fcn); + } + + octave_value set_meth = iter->second.get ("SetMethod"); + if (set_meth.is_function_handle ()) + { + octave_user_code *fcn + = set_meth.user_function_value ()->user_code_value (true); + if (fcn != nullptr) + m_methods_cache.push_back (fcn); + } + } } }
--- a/libinterp/parse-tree/pt-eval.cc Fri May 10 17:57:29 2024 -0400 +++ b/libinterp/parse-tree/pt-eval.cc Sat May 11 15:03:00 2024 -0400 @@ -3064,11 +3064,42 @@ cdef_class cls = cdm.find_class (dispatch_type, false); if (cls.ok () && cls.get_name () == dispatch_type) { - cdef_method meth = cls.find_method (method); - if (meth.ok () && meth.get_name () == method) - fcn = meth.get_function (); + if (! method.compare (0, 4, "get.")) + { + // find get method of classdef property + std::string prop_name = method.substr (4); + cdef_property prop = cls.find_property (prop_name); + if (prop.ok () && prop.get_name () == prop_name) + { + const octave_value& get_meth = prop.get ("GetMethod"); + if (get_meth.is_function_handle ()) + return get_meth.user_function_value ()->user_code_value (); + else + return nullptr; + } + } + else if (! method.compare (0, 4, "set.")) + { + // find set method of classdef property + std::string prop_name = method.substr (4); + cdef_property prop = cls.find_property (prop_name); + if (prop.ok () && prop.get_name () == prop_name) + { + const octave_value& set_meth = prop.get ("SetMethod"); + if (set_meth.is_function_handle ()) + return set_meth.user_function_value ()->user_code_value (); + else + return nullptr; + } + } else - return nullptr; + { + cdef_method meth = cls.find_method (method); + if (meth.ok () && meth.get_name () == method) + fcn = meth.get_function (); + else + return nullptr; + } } // If there is no classdef method, then try legacy classes.
--- a/scripts/plot/appearance/legend.m Fri May 10 17:57:29 2024 -0400 +++ b/scripts/plot/appearance/legend.m Sat May 11 15:03:00 2024 -0400 @@ -1072,7 +1072,7 @@ persistent lprops = {"color", "linestyle", "linewidth"}; persistent mprops = {"color", "marker", "markeredgecolor", ... "markerfacecolor", "markersize"}; - persistent pprops = {"edgecolor", "facecolor", "cdata", ... + persistent pprops = {"edgecolor", "facecolor", ... "linestyle", "linewidth", ... "marker", "markeredgecolor", ... "markerfacecolor", "markersize"}; @@ -1125,11 +1125,16 @@ case {"patch", "surface"} vals = get (hplt, pprops); + cdata = get (hplt, "cdata"); - hicon = __go_patch__ (hl, [pprops; vals]{:}); + hicon = __go_patch__ (hl, [pprops; vals]{:}, ... + "cdata", median (median (cdata, 1), 2)); ## Listeners safe_property_link (hplt(1), hicon, pprops); + addlistener (hplt, "cdata", ... + @(h, ~) set (hicon, "cdata", ... + median (median (get (h, "cdata"), 1), 2))); setappdata (hicon, "__creator__", typ); @@ -1171,7 +1176,9 @@ ## Main patch vals = get (hplt(1), pprops); - hicon = __go_patch__ (hl, [pprops; vals]{:}, ... + cdata = get (hplt(1), "cdata"); + hicon = __go_patch__ (hl, "cdata", cdata, ... + [pprops; vals]{:}, ... "pickableparts", "all", ... "buttondownfcn", ... {@execute_itemhit, hl, hplt, "icon"}); @@ -1181,15 +1188,17 @@ ## Additional patch for the inner contour vals = get (hplt(end), pprops); + cdata = get (hplt(end), "cdata"); htmp = __go_patch__ (hl, "handlevisibility", "off", ... - "xdata", 0, "ydata", 0, [pprops; vals]{:}, ... + "xdata", 0, "ydata", 0, "cdata", cdata, ... + [pprops; vals]{:}, ... "pickableparts", "all", ... "buttondownfcn", ... {@execute_itemhit, hl, hplt, "icon"}); ## Listeners - safe_property_link (hplt(1), hicon, pprops); - safe_property_link (hplt(end), htmp, pprops); + safe_property_link (hplt(1), hicon, [{"cdata"}, pprops]); + safe_property_link (hplt(end), htmp, [{"cdata"}, pprops]); addlistener (hicon, "ydata", ... @(h, ~) set (htmp, "ydata", get (h, "innerydata"))); addlistener (hicon, "xdata", ... @@ -1911,6 +1920,20 @@ %! title ("legend() works for surface objects too"); %!demo +%! clf; +%! [x,y,z] = meshgrid (-.2:0.02:.2, -.2:0.02:.2, -.2:0.02:.2); +%! val = (x.^2 + y.^2 + z.^2); +%! +%! h_axes = axes (); +%! view (3); +%! fv = isosurface (x, y, z, val, .039, z); +%! h_patch = patch (fv, "FaceColor", "flat", "EdgeColor", "none"); +%! view (3); +%! axis tight +%! axis equal +%! legend ({"colored patch"}); + +%!demo %! clf reset; # needed to undo colormap assignment in previous demo %! rand_2x3_data2 = [0.44804, 0.84368, 0.23012; 0.72311, 0.58335, 0.90531]; %! bar (rand_2x3_data2);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/classdef-debug/classdef_breakpoints2.m Sat May 11 15:03:00 2024 -0400 @@ -0,0 +1,19 @@ +classdef classdef_breakpoints2 < handle + properties (Dependent) + m_prop; + endproperties + properties (SetAccess=private) + m_prop_value = []; + endproperties + methods + function this = classdef_breakpoints2 (prop) + this.m_prop = prop; + endfunction + function val = get.m_prop (this) + val = this.m_prop_value; + endfunction + function set.m_prop (this, val) + this.m_prop_value = val; + endfunction + endmethods +endclassdef
--- a/test/classdef-debug/module.mk Fri May 10 17:57:29 2024 -0400 +++ b/test/classdef-debug/module.mk Sat May 11 15:03:00 2024 -0400 @@ -1,5 +1,6 @@ classdef_breakpoints_TEST_FILES = \ %reldir%/classdef_breakpoints.m \ + %reldir%/classdef_breakpoints2.m \ %reldir%/test-classdef-breakpoints.tst TEST_FILES += $(classdef_breakpoints_TEST_FILES)
--- a/test/classdef-debug/test-classdef-breakpoints.tst Fri May 10 17:57:29 2024 -0400 +++ b/test/classdef-debug/test-classdef-breakpoints.tst Sat May 11 15:03:00 2024 -0400 @@ -30,6 +30,7 @@ %! dbclear classdef_breakpoints; %! assert_dbstatus ([]); %! unwind_protect_cleanup +%! dbclear classdef_breakpoints; %! if (isguirunning ()) %! __event_manager_gui_preference__ ("editor/show_dbg_file", orig_show_dbg); %! endif @@ -59,13 +60,14 @@ %! dbclear classdef_breakpoints; %! assert_dbstatus ([]); %! unwind_protect_cleanup +%! dbclear classdef_breakpoints; %! if (isguirunning ()) %! __event_manager_gui_preference__ ("editor/show_dbg_file", orig_show_dbg); %! endif %! end_unwind_protect ## Try to add breakpoint in non-existent method -%!test <65610*> +%!test <*65610> %! if (isguirunning ()) %! orig_show_dbg = __event_manager_gui_preference__ ("editor/show_dbg_file", %! "false"); @@ -89,7 +91,64 @@ %! dbstop classdef_breakpoints 19; %! assert_dbstatus ([20]); %! unwind_protect_cleanup +%! dbclear classdef_breakpoints; +%! if (isguirunning ()) +%! __event_manager_gui_preference__ ("editor/show_dbg_file", orig_show_dbg); +%! endif +%! end_unwind_protect + +## Set breakpoints in set or get methods by line numbers +%!test <*65610> +%! if (isguirunning ()) +%! orig_show_dbg = __event_manager_gui_preference__ ("editor/show_dbg_file", +%! "false"); +%! endif +%! unwind_protect +%! ## Add breakpoints in different member functions using line numbers. +%! dbstop classdef_breakpoints2 13 16 10; +%! assert_dbstatus ([10, 13, 16]); +%! +%! ## Remove one breakpoint and confirm the others remain. +%! dbclear classdef_breakpoints2 16; +%! assert_dbstatus ([10, 13]); +%! +%! ## Clear all breakpoints, none should be left. +%! dbclear classdef_breakpoints2; +%! assert_dbstatus ([]); +%! unwind_protect_cleanup +%! dbclear classdef_breakpoints2; %! if (isguirunning ()) %! __event_manager_gui_preference__ ("editor/show_dbg_file", orig_show_dbg); %! endif %! end_unwind_protect + +## Set breakpoints in set or get methods by method name +%!test +%! if (isguirunning ()) +%! orig_show_dbg = __event_manager_gui_preference__ ("editor/show_dbg_file", +%! "false"); +%! endif +%! unwind_protect +%! ## Add breakpoint in constructor +%! dbstop @classdef_breakpoints2/classdef_breakpoints2; +%! assert_dbstatus ([10]); +%! +%! ## Add breakpoints in methods. +%! dbstop @classdef_breakpoints2/get.m_prop; +%! dbstop @classdef_breakpoints2/set.m_prop; +%! assert_dbstatus ([10, 13, 16]); +%! +%! ## Remove breakpoint from one method. +%! dbclear @classdef_breakpoints2/get.m_prop; +%! assert_dbstatus ([10, 16]); +%! +%! ## Clear all breakpoints, none should be left. +%! dbclear classdef_breakpoints2; +%! assert_dbstatus ([]); +%! unwind_protect_cleanup +%! dbclear classdef_breakpoints2; +%! if (isguirunning ()) +%! __event_manager_gui_preference__ ("editor/show_dbg_file", orig_show_dbg); +%! endif +%! end_unwind_protect +