# HG changeset patch # User John W. Eaton # Date 1389128874 18000 # Node ID 8f256148d82b82e6ab9a401dea24b8982f74c9a2 # Parent 3cad99b56fa7015b83e128c7477f6e2c3ce67759# Parent e42d4f1527660a8153cb44fc64bff5fddb42dcc7 maint: Periodic merge of gui-release to default. diff -r e42d4f152766 -r 8f256148d82b NEWS --- a/NEWS Tue Jan 07 16:07:21 2014 -0500 +++ b/NEWS Tue Jan 07 16:07:54 2014 -0500 @@ -1,3 +1,47 @@ +Summary of important user-visible changes for version 4.2: +--------------------------------------------------------- + + ** Other new functions added in 4.2: + + dir_in_loadpath + + ** Deprecated functions. + + The following functions were deprecated in Octave 3.8 and have been + removed from Octave 4.2. + + default_save_options java_new + gen_doc_cache java_set + interp1q java_unsigned_conversion + isequalwithequalnans javafields + java_convert_matrix javamethods + java_debug re_read_readline_init_file + java_get read_readline_init_file + java_invoke saving_history + + + The following functions have been deprecated in Octave 4.2 and will + be removed from Octave 4.6 (or whatever version is the second major + release after 4.2): + + find_dir_in_path + + + The following keywords were deprecated in Octave 3.8 and have been + removed from Octave 4.2 + + static + + The following configuration variables were deprecated in Octave 3.8 + and have been removed from Octave 4.2 + + CC_VERSION (now GCC_VERSION) + CXX_VERSION (now GXX_VERSION) + + The internal class was deprecated in Octave 3.8 and has + been removed from Octave 4.2. Replacement classes are + (struct array) or for a single structure. + Summary of important user-visible changes for version 4.0: --------------------------------------------------------- @@ -23,7 +67,7 @@ ** Other new functions added in 4.0.0: - validateattributes + validateattributes ** Deprecated functions. diff -r e42d4f152766 -r 8f256148d82b build-aux/common.mk --- a/build-aux/common.mk Tue Jan 07 16:07:21 2014 -0500 +++ b/build-aux/common.mk Tue Jan 07 16:07:54 2014 -0500 @@ -107,8 +107,6 @@ # C compiler flags. CC = @CC@ -## FIXME: CC_VERSION is deprecated and should be removed in version 3.12 -CC_VERSION = @CC_VERSION@ GCC_VERSION = @GCC_VERSION@ CPICFLAG = @CPICFLAG@ XTRA_CFLAGS = @XTRA_CFLAGS@ @@ -131,8 +129,6 @@ # C++ compiler flags. CXX = @CXX@ -## FIXME: CXX_VERSION is deprecated and should be removed in version 3.12 -CXX_VERSION = @CXX_VERSION@ GXX_VERSION = @GXX_VERSION@ CXXCPP = @CXXCPP@ CXXPICFLAG = @CXXPICFLAG@ @@ -518,7 +514,6 @@ -e "s|%OCTAVE_CONF_CANONICAL_HOST_TYPE%|\"${canonical_host_type}\"|" \ -e "s|%OCTAVE_CONF_CARBON_LIBS%|\"${CARBON_LIBS}\"|" \ -e "s|%OCTAVE_CONF_CC%|\"${CC}\"|" \ - -e "s|%OCTAVE_CONF_CC_VERSION%|\"${CC_VERSION}\"|" \ -e "s|%OCTAVE_CONF_CCOLAMD_CPPFLAGS%|\"${CCOLAMD_CPPFLAGS}\"|" \ -e "s|%OCTAVE_CONF_CCOLAMD_LDFLAGS%|\"${CCOLAMD_LDFLAGS}\"|" \ -e "s|%OCTAVE_CONF_CCOLAMD_LIBS%|\"${CCOLAMD_LIBS}\"|" \ diff -r e42d4f152766 -r 8f256148d82b configure.ac --- a/configure.ac Tue Jan 07 16:07:21 2014 -0500 +++ b/configure.ac Tue Jan 07 16:07:54 2014 -0500 @@ -19,7 +19,7 @@ ### . AC_PREREQ([2.62]) -AC_INIT([GNU Octave], [3.9.0+], [http://octave.org/bugs.html], [octave]) +AC_INIT([GNU Octave], [4.1.0+], [http://octave.org/bugs.html], [octave]) dnl Note that the version number is duplicated here and in AC_INIT dnl because AC_INIT requires it to be static, not computed from @@ -329,10 +329,6 @@ fi AC_SUBST(GXX_VERSION) -## FIXME: CXX_VERSION is deprecated and should be removed in Octave version 3.12 -CXX_VERSION=$gxx_version -AC_SUBST(CXX_VERSION) - ### Determine which C compiler to use (we expect to find gcc). AC_PROG_CC @@ -379,10 +375,6 @@ fi AC_SUBST(GCC_VERSION) -## FIXME: CC_VERSION is deprecated and should be removed in Octave version 3.12 -CC_VERSION=$GCC_VERSION -AC_SUBST(CC_VERSION) - ### Also check g++ version number, it might be different from the ## gcc version number. diff -r e42d4f152766 -r 8f256148d82b doc/interpreter/func.txi --- a/doc/interpreter/func.txi Tue Jan 07 16:07:21 2014 -0500 +++ b/doc/interpreter/func.txi Tue Jan 07 16:07:54 2014 -0500 @@ -802,7 +802,7 @@ @DOCSTRING(command_line_path) -@DOCSTRING(find_dir_in_path) +@DOCSTRING(dir_in_loadpath) @node Subfunctions @subsection Subfunctions diff -r e42d4f152766 -r 8f256148d82b doc/interpreter/grammar.txi --- a/doc/interpreter/grammar.txi Tue Jan 07 16:07:21 2014 -0500 +++ b/doc/interpreter/grammar.txi Tue Jan 07 16:07:54 2014 -0500 @@ -49,9 +49,8 @@ @item @code{function} @tab @code{global} @tab @code{if} @item @code{methods} @tab @code{otherwise} @tab @code{parfor} @item @code{persistent} @tab @code{properties} @tab @code{return} -@item @code{static} @tab @code{switch} @tab @code{try} -@item @code{until} @tab @code{unwind_protect} @tab @code{unwind_protect_cleanup} -@item @code{while} +@item @code{switch} @tab @code{try} @tab @code{until} +@item @code{unwind_protect} @tab @code{unwind_protect_cleanup} @tab @code{while} @end multitable The function @code{iskeyword} can be used to quickly check whether an diff -r e42d4f152766 -r 8f256148d82b doc/interpreter/macros.texi --- a/doc/interpreter/macros.texi Tue Jan 07 16:07:21 2014 -0500 +++ b/doc/interpreter/macros.texi Tue Jan 07 16:07:54 2014 -0500 @@ -28,14 +28,14 @@ @c which is `XXX'. This looks particularly bad when the macro body is @c single or double-quoted text, such as a property value `"position"' @ifinfo -@rmacro qcode{arg} +@macro qcode{arg} \arg\ -@end rmacro +@end macro @end ifinfo @ifnotinfo -@rmacro qcode{arg} +@macro qcode{arg} @code{\arg\} -@end rmacro +@end macro @end ifnotinfo @c The following macro is used for the on-line help system, but we don't diff -r e42d4f152766 -r 8f256148d82b doc/interpreter/plot.txi --- a/doc/interpreter/plot.txi Tue Jan 07 16:07:21 2014 -0500 +++ b/doc/interpreter/plot.txi Tue Jan 07 16:07:54 2014 -0500 @@ -1226,18 +1226,21 @@ @noindent sets the range of the x-axis for the current axes object in the current -figure to @samp{[-10, 10]}. Additionally, calling set with a graphics -object index as the only argument returns a structure containing the -default values for all the properties for the given object type. For -example, +figure to @samp{[-10, 10]}. + +Default property values can also be queried if the @code{set} function is +called without a value argument. When only one argument is given (a graphic +handle) then a structure with defaults for all properties of the given object +type is returned. For example, @example set (gca ()) @end example @noindent -returns a structure containing the default property values for axes -objects. +returns a structure containing the default property values for axes objects. +If @code{set} is called with two arguments (a graphic handle and a property +name) then only the defaults for the requested property are returned. @DOCSTRING(get) diff -r e42d4f152766 -r 8f256148d82b doc/interpreter/var.txi --- a/doc/interpreter/var.txi Tue Jan 07 16:07:21 2014 -0500 +++ b/doc/interpreter/var.txi Tue Jan 07 16:07:54 2014 -0500 @@ -221,8 +221,7 @@ @end example The behavior of persistent variables is equivalent to the behavior of -static variables in C@. The command @code{static} in Octave is also -recognized and is equivalent to @code{persistent}. +static variables in C@. Like global variables, a persistent variable may only be initialized once. For example, after executing the following code diff -r e42d4f152766 -r 8f256148d82b libgui/languages/pt_BR.ts diff -r e42d4f152766 -r 8f256148d82b libgui/src/m-editor/find-dialog.cc --- a/libgui/src/m-editor/find-dialog.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libgui/src/m-editor/find-dialog.cc Tue Jan 07 16:07:54 2014 -0500 @@ -211,7 +211,8 @@ void find_dialog::find (bool forward) { - int line = -1, col = -1; + int line, col; + line = col = -1; bool do_wrap = _wrap_check_box->isChecked (); bool do_forward = forward; diff -r e42d4f152766 -r 8f256148d82b libgui/src/qtinfo/parser.cc --- a/libgui/src/qtinfo/parser.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libgui/src/qtinfo/parser.cc Tue Jan 07 16:07:54 2014 -0500 @@ -501,7 +501,8 @@ void parser::real_position (int pos, QFileInfo & file_info, int & real_pos) { - int header = -1, sum = 0; + int header = -1; + int sum = 0; for (int i = 0; i < _info_file_real_size_list.size (); i++) { info_file_item item = _info_file_real_size_list.at (i); diff -r e42d4f152766 -r 8f256148d82b libinterp/Makefile.am diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/__contourc__.cc --- a/libinterp/corefcn/__contourc__.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/__contourc__.cc Tue Jan 07 16:07:54 2014 -0500 @@ -307,10 +307,10 @@ if (args.length () == 4) { - RowVector X = args (0).row_vector_value (); - RowVector Y = args (1).row_vector_value (); - Matrix Z = args (2).matrix_value (); - RowVector L = args (3).row_vector_value (); + RowVector X = args(0).row_vector_value (); + RowVector Y = args(1).row_vector_value (); + Matrix Z = args(2).matrix_value (); + RowVector L = args(3).row_vector_value (); if (! error_state) { diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/__pchip_deriv__.cc --- a/libinterp/corefcn/__pchip_deriv__.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/__pchip_deriv__.cc Tue Jan 07 16:07:54 2014 -0500 @@ -59,7 +59,7 @@ octave_value retval; const int nargin = args.length (); - bool rows = (nargin == 3 && args (2).uint_value () == 2); + bool rows = (nargin == 3 && args(2).uint_value () == 2); if (nargin >= 2) { diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/balance.cc --- a/libinterp/corefcn/balance.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/balance.cc Tue Jan 07 16:07:54 2014 -0500 @@ -144,7 +144,8 @@ if (AEPcase) { // Algebraic eigenvalue problem. - bool noperm = false, noscal = false; + bool noperm = false; + bool noscal = false; if (nargin > 1) { std::string a1s = args(1).string_value (); diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/besselj.cc --- a/libinterp/corefcn/besselj.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/besselj.cc Tue Jan 07 16:07:54 2014 -0500 @@ -598,7 +598,7 @@ { int idx = nargin == 1 ? 0 : 1; - if (args (idx).is_single_type ()) + if (args(idx).is_single_type ()) { FloatComplexNDArray z = args(idx).float_complex_array_value (); diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/bsxfun.cc --- a/libinterp/corefcn/bsxfun.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/bsxfun.cc Tue Jan 07 16:07:54 2014 -0500 @@ -201,7 +201,8 @@ bsxfun_builtin_op op = bsxfun_builtin_lookup (name); if (op != bsxfun_builtin_unknown) { - builtin_type_t btyp_a = a.builtin_type (), btyp_b = b.builtin_type (); + builtin_type_t btyp_a = a.builtin_type (); + builtin_type_t btyp_b = b.builtin_type (); // Simplify single/double combinations. if (btyp_a == btyp_float && btyp_b == btyp_double) @@ -351,8 +352,8 @@ || args(0).is_inline_function ())) error ("bsxfun: F must be a string or function handle"); - const octave_value A = args (1); - const octave_value B = args (2); + const octave_value A = args(1); + const octave_value B = args(2); if (func.is_builtin_function () || (func.is_function_handle () diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/cellfun.cc --- a/libinterp/corefcn/cellfun.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/cellfun.cc Tue Jan 07 16:07:54 2014 -0500 @@ -1783,7 +1783,8 @@ NDA parray = array.permute (perm); - octave_idx_type nela = arraydv.numel (), nelc = celldv.numel (); + octave_idx_type nela = arraydv.numel (); + octave_idx_type nelc = celldv.numel (); parray = parray.reshape (dim_vector (nela, nelc)); Cell retval (celldv); @@ -1901,7 +1902,7 @@ octave_value array = args(0); Array dimv; if (nargin > 1) - dimv = args (1).int_vector_value (true); + dimv = args(1).int_vector_value (true); if (error_state) ; @@ -2036,7 +2037,8 @@ if (ivec >= 0) { // Vector split. Use 1D indexing. - octave_idx_type l = 0, nidx = (ivec == 0 ? nridx : ncidx); + octave_idx_type l = 0; + octave_idx_type nidx = (ivec == 0 ? nridx : ncidx); for (octave_idx_type i = 0; i < nidx; i++) { octave_idx_type u = l + d[ivec](i); diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/data.cc --- a/libinterp/corefcn/data.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/data.cc Tue Jan 07 16:07:54 2014 -0500 @@ -302,7 +302,8 @@ { octave_value retval; - octave_value arg0 = x, arg1 = y; + octave_value arg0 = x; + octave_value arg1 = y; if (! arg0.is_numeric_type ()) gripe_wrong_type_arg ("hypot", arg0); else if (! arg1.is_numeric_type ()) @@ -1353,6 +1354,11 @@ %!assert (diag ({1}, 2, 3), {1,[],[]; [],[],[]}); %!assert (diag ({1,2}, 3, 4), {1,[],[],[]; [],2,[],[]; [],[],[],[]}); +## Test out-of-range diagonals +%!assert (diag (ones (3,3), 4), zeros (0, 1)) +%!assert (diag (cell (3,3), 4), cell (0, 1)) +%!assert (diag (sparse (ones (3,3)), 4), sparse (zeros (0, 1))) + %% Test input validation %!error diag () %!error diag (1,2,3,4) @@ -1836,7 +1842,7 @@ // and then directly resize. However, for some types there might // be some additional setup needed, and so this should be avoided. - octave_value tmp = args (0); + octave_value tmp = args(0); tmp = tmp.resize (dim_vector (0,0)).resize (dv); if (error_state) @@ -1850,12 +1856,12 @@ // Can't fast return here to skip empty matrices as something // like cat (1,[],single ([])) must return an empty matrix of // the right type. - tmp = do_cat_op (tmp, args (j), ra_idx); + tmp = do_cat_op (tmp, args(j), ra_idx); if (error_state) return retval; - dim_vector dv_tmp = args (j).dims (); + dim_vector dv_tmp = args(j).dims (); if (dim >= dv_len) { @@ -6708,7 +6714,8 @@ if (! error_state) { - octave_value vals = args(1), zero = args (2); + octave_value vals = args(1); + octave_value zero = args(2); switch (vals.builtin_type ()) { @@ -6790,7 +6797,8 @@ else if (idx.extent (n) > n) error ("accumdim: index out of range"); - dim_vector vals_dim = vals.dims (), rdv = vals_dim; + dim_vector vals_dim = vals.dims (); + dim_vector rdv = vals_dim; if (dim < 0) dim = vals.dims ().first_non_singleton (); @@ -6869,7 +6877,8 @@ dim_vector dv = mask.dims (); NDT retval (dv); - bool tscl = tval.numel () == 1, fscl = fval.numel () == 1; + bool tscl = tval.numel () == 1; + bool fscl = fval.numel () == 1; if ((! tscl && tval.dims () != dv) || (! fscl && fval.dims () != dv)) @@ -6879,14 +6888,16 @@ T *rv = retval.fortran_vec (); octave_idx_type n = retval.numel (); - const T *tv = tval.data (), *fv = fval.data (); + const T *tv = tval.data (); + const T *fv = fval.data (); const bool *mv = mask.data (); if (tscl) { if (fscl) { - T ts = tv[0], fs = fv[0]; + T ts = tv[0]; + T fs = fv[0]; for (octave_idx_type i = 0; i < n; i++) rv[i] = mv[i] ? ts : fs; } @@ -6963,7 +6974,8 @@ else { boolNDArray mask = mask_val.bool_array_value (); - octave_value tval = args(1), fval = args(2); + octave_value tval = args(1); + octave_value fval = args(2); if (tval.is_double_type () && fval.is_double_type ()) { if (tval.is_complex_type () || fval.is_complex_type ()) @@ -7241,7 +7253,8 @@ assert (rep.ndims () == 2 && rep.rows () == 2); - octave_idx_type n = rep.columns (), l = 0; + octave_idx_type n = rep.columns (); + octave_idx_type l = 0; for (octave_idx_type i = 0; i < n; i++) { octave_idx_type k = rep(1, i); diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/dlmread.cc --- a/libinterp/corefcn/dlmread.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/dlmread.cc Tue Jan 07 16:07:54 2014 -0500 @@ -264,12 +264,15 @@ } // Take a subset if a range was given. - octave_idx_type r0 = 0, c0 = 0, r1 = idx_max-1, c1 = idx_max-1; + octave_idx_type r0 = 0; + octave_idx_type c0 = 0; + octave_idx_type r1 = idx_max-1; + octave_idx_type c1 = idx_max-1; if (nargin > 2) { if (nargin == 3) { - if (!parse_range_spec (args (2), r0, c0, r1, c1)) + if (!parse_range_spec (args(2), r0, c0, r1, c1)) error ("dlmread: error parsing RANGE"); } else if (nargin == 4) @@ -287,7 +290,12 @@ if (!error_state) { - octave_idx_type i = 0, j = 0, r = 1, c = 1, rmax = 0, cmax = 0; + octave_idx_type i = 0; + octave_idx_type j = 0; + octave_idx_type r = 1; + octave_idx_type c = 1; + octave_idx_type rmax = 0; + octave_idx_type cmax = 0; Matrix rdata; ComplexMatrix cdata; diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/dot.cc --- a/libinterp/corefcn/dot.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/dot.cc Tue Jan 07 16:07:54 2014 -0500 @@ -128,11 +128,13 @@ return retval; } - octave_value argx = args(0), argy = args(1); + octave_value argx = args(0); + octave_value argy = args(1); if (argx.is_numeric_type () && argy.is_numeric_type ()) { - dim_vector dimx = argx.dims (), dimy = argy.dims (); + dim_vector dimx = argx.dims (); + dim_vector dimy = argy.dims (); bool match = dimx == dimy; if (! match && nargin == 2 && dimx.is_vector () && dimy.is_vector ()) @@ -291,13 +293,18 @@ return retval; } - octave_value argx = args(0), argy = args(1); + octave_value argx = args(0); + octave_value argy = args(1); if (argx.is_numeric_type () && argy.is_numeric_type ()) { - const dim_vector dimx = argx.dims (), dimy = argy.dims (); + const dim_vector dimx = argx.dims (); + const dim_vector dimy = argy.dims (); int nd = dimx.length (); - octave_idx_type m = dimx(0), k = dimx(1), n = dimy(1), np = 1; + octave_idx_type m = dimx(0); + octave_idx_type k = dimx(1); + octave_idx_type n = dimy(1); + octave_idx_type np = 1; bool match = dimy(0) == k && nd == dimy.length (); dim_vector dimz = dim_vector::alloc (nd); dimz(0) = m; diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/eig.cc --- a/libinterp/corefcn/eig.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/eig.cc Tue Jan 07 16:07:54 2014 -0500 @@ -62,8 +62,8 @@ octave_value arg_a, arg_b; - octave_idx_type nr_a = 0, nr_b = 0; - octave_idx_type nc_a = 0, nc_b = 0; + octave_idx_type nr_a, nr_b, nc_a, nc_b; + nr_a = nr_b = nc_a = nc_b = 0; arg_a = args(0); nr_a = arg_a.rows (); diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/file-io.cc --- a/libinterp/corefcn/file-io.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/file-io.cc Tue Jan 07 16:07:54 2014 -0500 @@ -271,7 +271,7 @@ if (nargin == 1) { - int fid = octave_stream_list::get_file_number (args (0)); + int fid = octave_stream_list::get_file_number (args(0)); octave_stream os = octave_stream_list::lookup (fid, "fclear"); @@ -305,7 +305,7 @@ { // FIXME: any way to avoid special case for stdout? - int fid = octave_stream_list::get_file_number (args (0)); + int fid = octave_stream_list::get_file_number (args(0)); if (fid == 1) { @@ -1338,7 +1338,7 @@ tmp_args (0) = 0.0; for (int i = 0; i < nargin; i++) - tmp_args (i+1) = args (i); + tmp_args(i+1) = args(i); return Ffscanf (tmp_args, nargout); } @@ -1404,9 +1404,13 @@ DEFUN (fread, args, , "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {[@var{val}, @var{count}] =} fread (@var{fid}, @var{size}, @var{precision}, @var{skip}, @var{arch})\n\ -Read binary data of type @var{precision} from the specified file ID\n\ -@var{fid}.\n\ +@deftypefn {Built-in Function} {@var{val} =} fread (@var{fid})\n\ +@deftypefnx {Built-in Function} {@var{val} =} fread (@var{fid}, @var{size})\n\ +@deftypefnx {Built-in Function} {@var{val} =} fread (@var{fid}, @var{size}, @var{precision})\n\ +@deftypefnx {Built-in Function} {@var{val} =} fread (@var{fid}, @var{size}, @var{precision}, @var{skip})\n\ +@deftypefnx {Built-in Function} {@var{val} =} fread (@var{fid}, @var{size}, @var{precision}, @var{skip}, @var{arch})\n\ +@deftypefnx {Built-in Function} {[@var{val}, @var{count}] =} fread (@dots{})\n\ +Read binary data from the specified file ID @var{fid}.\n\ \n\ The optional argument @var{size} specifies the amount of data to read\n\ and may be one of\n\ @@ -1559,8 +1563,8 @@ IEEE little endian.\n\ @end table\n\ \n\ -The data read from the file is returned in @var{val}, and the number of\n\ -values read is returned in @code{count}\n\ +The output argument @var{val} contains the data read from the file.\n\ +The optional return value @var{count} contains the number of elements read.\n\ @seealso{fwrite, fgets, fgetl, fscanf, fopen}\n\ @end deftypefn") { diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/find.cc --- a/libinterp/corefcn/find.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/find.cc Tue Jan 07 16:07:54 2014 -0500 @@ -61,7 +61,8 @@ case 2: { Array jdx (idx.dims ()); - octave_idx_type n = idx.length (), nr = nda.rows (); + octave_idx_type n = idx.length (); + octave_idx_type nr = nda.rows (); for (octave_idx_type i = 0; i < n; i++) { jdx.xelem (i) = idx.xelem (i) / nr; diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/gcd.cc --- a/libinterp/corefcn/gcd.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/gcd.cc Tue Jan 07 16:07:54 2014 -0500 @@ -125,8 +125,9 @@ double aa = fabs (a); double bb = fabs (b); - double xx = 0, yy = 1; - double lx = 1, ly = 0; + double xx, lx, yy, ly; + xx = 0, lx = 1; + yy = 1, ly = 0; while (bb != 0) { @@ -161,7 +162,8 @@ (*current_liboctave_error_handler) ("gcd: all complex parts must be integers"); - std::complex aa = a, bb = b; + std::complex aa = a; + std::complex bb = b; bool swapped = false; if (abs (aa) < abs (bb)) { @@ -169,8 +171,9 @@ swapped = true; } - std::complex xx = 0, lx = 1; - std::complex yy = 1, ly = 0; + std::complex xx, lx, yy, ly; + xx = 0, lx = 1; + yy = 1, ly = 0; while (abs(bb) != 0) { @@ -204,8 +207,9 @@ { T aa = a.abs ().value (); T bb = b.abs ().value (); - T xx = 0, lx = 1; - T yy = 1, ly = 0; + T xx, lx, yy, ly; + xx = 0, lx = 1; + yy = 1, ly = 0; while (bb != 0) { @@ -347,7 +351,8 @@ bool incb = bb.numel () != 1; T *gptr = gg.fortran_vec (); - T *xptr = xx.fortran_vec (), *yptr = yy.fortran_vec (); + T *xptr = xx.fortran_vec (); + T *yptr = yy.fortran_vec (); octave_idx_type n = gg.numel (); for (octave_idx_type i = 0; i < n; i++) diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/gl-render.cc --- a/libinterp/corefcn/gl-render.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/gl-render.cc Tue Jan 07 16:07:54 2014 -0500 @@ -147,7 +147,8 @@ { // FIXME: dim_vectors hold octave_idx_type values. // Should we check for dimensions larger than intmax? - int h = dv(0), w = dv(1), tw, th; + int h, w, tw, th; + h = dv(0), w = dv(1); GLuint id; bool ok = true; @@ -441,7 +442,7 @@ // tessellation process might re-order the vertices, such that // the first one you get here might not be the first one of the face; // but I can't figure out the actual reason. - if (color_mode > 0 && (first || color_mode == 2)) + if (color_mode == 2) { Matrix col = v->color; @@ -458,7 +459,7 @@ for (int k = 0; k < 3; k++) buf[k] = (v->diffuse * col(k)); - glMaterialfv (LIGHT_MODE, GL_AMBIENT, buf); + glMaterialfv (LIGHT_MODE, GL_DIFFUSE, buf); } } } @@ -1002,7 +1003,8 @@ Matrix xticks = xform.xscale (props.get_xtick ().matrix_value ()); Matrix xmticks = xform.xscale (props.get_xmtick ().matrix_value ()); string_vector xticklabels = props.get_xticklabel ().all_strings (); - int wmax = 0, hmax = 0; + int wmax = 0; + int hmax = 0; bool tick_along_z = nearhoriz || xisinf (fy); bool mirror = props.is_box () && xstate != AXE_ANY_DIR; @@ -1110,7 +1112,8 @@ Matrix yticks = xform.yscale (props.get_ytick ().matrix_value ()); Matrix ymticks = xform.yscale (props.get_ymtick ().matrix_value ()); string_vector yticklabels = props.get_yticklabel ().all_strings (); - int wmax = 0, hmax = 0; + int wmax = 0; + int hmax = 0; bool tick_along_z = nearhoriz || xisinf (fx); bool mirror = props.is_box () && ystate != AXE_ANY_DIR && (! props.has_property ("__plotyy_axes__")); @@ -1209,7 +1212,8 @@ Matrix zticks = xform.zscale (props.get_ztick ().matrix_value ()); Matrix zmticks = xform.zscale (props.get_zmtick ().matrix_value ()); string_vector zticklabels = props.get_zticklabel ().all_strings (); - int wmax = 0, hmax = 0; + int wmax = 0; + int hmax = 0; bool mirror = props.is_box () && zstate != AXE_ANY_DIR; set_color (props.get_zcolor_rgb ()); @@ -1562,7 +1566,8 @@ const Matrix y = xform.yscale (props.get_ydata ().matrix_value ()); const Matrix z = xform.zscale (props.get_zdata ().matrix_value ()); - int zr = z.rows (), zc = z.columns (); + int zr = z.rows (); + int zc = z.columns (); NDArray c; const NDArray n = props.get_vertexnormals ().array_value (); @@ -2332,7 +2337,38 @@ tess.begin_polygon (true); tess.begin_contour (); - for (int j = 0; j < count_f(i); j++) + if (count_f(i) > 0) + { + vertex_data::vertex_data_rep *vv = vdata[i].get_rep (); + + if (fc_mode == 1) + { + // For "flat" shading, use color of 1st vertex. + Matrix col = vv->color; + + if (col.numel () == 3) + { + glColor3dv (col.data ()); + if (fl_mode > 0) + { + float cb[4] = { 0, 0, 0, 1 }; + + for (int k = 0; k < 3; k++) + cb[k] = (vv->ambient * col(k)); + glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb); + + for (int k = 0; k < 3; k++) + cb[k] = (vv->diffuse * col(k)); + glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb); + } + } + } + + tess.add_vertex (vv->coords.fortran_vec (), vv); + } + + // Add remaining vertices. + for (int j = 1; j < count_f(i); j++) { vertex_data::vertex_data_rep *vv = vdata[i+j*fr].get_rep (); @@ -2552,7 +2588,8 @@ { octave_value cdata = props.get_color_data (); dim_vector dv (cdata.dims ()); - int h = dv(0), w = dv(1); + int h = dv(0); + int w = dv(1); Matrix x = props.get_xdata ().matrix_value (); Matrix y = props.get_ydata ().matrix_value (); @@ -2610,8 +2647,9 @@ // viewport/clipping plane so we must do the clipping // ourselfes - only draw part of the image - int j0 = 0, j1 = w; - int i0 = 0, i1 = h; + int j0, j1, i0, i1; + j0 = 0, j1 = w; + i0 = 0, i1 = h; float im_xmin = x(0) - nor_dx/2; float im_xmax = x(1) + nor_dx/2; diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/gl2ps-renderer.cc --- a/libinterp/corefcn/gl2ps-renderer.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/gl2ps-renderer.cc Tue Jan 07 16:07:54 2014 -0500 @@ -44,7 +44,8 @@ { in_draw = true; - GLint buffsize = 0, state = GL2PS_OVERFLOW; + GLint buffsize = 0; + GLint state = GL2PS_OVERFLOW; GLint viewport[4]; glGetIntegerv (GL_VIEWPORT, viewport); @@ -222,7 +223,8 @@ set_color (props.get_color_rgb ()); const Matrix pos = get_transform ().scale (props.get_data_position ()); - int halign = 0, valign = 0; + int halign = 0; + int valign = 0; if (props.horizontalalignment_is ("center")) halign = 1; diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/graphics.cc --- a/libinterp/corefcn/graphics.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/graphics.cc Tue Jan 07 16:07:54 2014 -0500 @@ -1012,7 +1012,7 @@ for (std::set::const_iterator it = possible_vals.begin (); it != possible_vals.end (); it++) { - if (retval == "") + if (retval.empty ()) { if (*it == default_value ()) retval = "{" + *it + "}"; @@ -1027,8 +1027,10 @@ retval += " | " + *it; } } - if (retval != "") + + if (! retval.empty ()) retval = "[ " + retval + " ]"; + return retval; } @@ -1044,10 +1046,13 @@ } bool -color_values::str2rgb (std::string str) -{ +color_values::str2rgb (const std::string& str_arg) +{ + bool retval = true; + double tmp_rgb[3] = {0, 0, 0}; - bool retval = true; + + std::string str = str_arg; unsigned int len = str.length (); std::transform (str.begin (), str.end (), str.begin (), tolower); @@ -2976,7 +2981,8 @@ } } } - if (retval != "") + + if (! retval.empty ()) retval += "\n"; } else @@ -2985,6 +2991,33 @@ return retval; } +std::string +base_graphics_object::value_as_string (const std::string& prop) +{ + std::string retval; + + if (valid_object ()) + { + if (prop != "children") + { + property p = get_properties ().get_property (prop); + + if (p.ok () && ! p.is_hidden ()) + { + if (p.is_radio ()) + retval += p.values_as_string (); + } + } + + if (! retval.empty ()) + retval += "\n"; + } + else + error ("base_graphics_object::value_as_string: invalid graphics object"); + + return retval; +} + octave_scalar_map base_graphics_object::values_as_struct (void) { @@ -4704,7 +4737,8 @@ if (camerapositionmode_is ("auto")) { Matrix tview = get_view ().matrix_value (); - double az = tview(0), el = tview(1); + double az = tview(0); + double el = tview(1); double d = 5 * sqrt (pb(0)*pb(0)+pb(1)*pb(1)+pb(2)*pb(2)); if (el == 90 || el == -90) @@ -4729,7 +4763,8 @@ if (cameraupvectormode_is ("auto")) { Matrix tview = get_view ().matrix_value (); - double az = tview(0), el = tview(1); + double az = tview(0); + double el = tview(1); if (el == 90 || el == -90) { @@ -4791,7 +4826,8 @@ translate (x_view, -0.5, -0.5, -0.5); Matrix x_cube = x_view * unit_cube (); - ColumnVector cmin = x_cube.row_min (), cmax = x_cube.row_max (); + ColumnVector cmin = x_cube.row_min (); + ColumnVector cmax = x_cube.row_max (); double xM = cmax(0)-cmin(0); double yM = cmax(1)-cmin(1); @@ -4897,9 +4933,11 @@ const Matrix xlims = xform.xscale (get_xlim ().matrix_value ()); const Matrix ylims = xform.yscale (get_ylim ().matrix_value ()); const Matrix zlims = xform.zscale (get_zlim ().matrix_value ()); - double x_min = xlims(0), x_max = xlims(1); - double y_min = ylims(0), y_max = ylims(1); - double z_min = zlims(0), z_max = zlims(1); + + double x_min, x_max, y_min, y_max, z_min, z_max; + x_min = xlims(0), x_max = xlims(1); + y_min = ylims(0), y_max = ylims(1); + z_min = zlims(0), z_max = zlims(1); ColumnVector p1, p2, dir (3); @@ -5139,7 +5177,9 @@ get_xticklabel ().all_strings (), get_xlim ().matrix_value ()); - double wmax = ext(0), hmax = ext(1), angle = 0; + double wmax = ext(0); + double hmax = ext(1); + double angle = 0; ColumnVector p = graphics_xform::xform_vector ((xpTickN+xpTick)/2, ypTick, zpTick); @@ -5240,7 +5280,9 @@ get_yticklabel ().all_strings (), get_ylim ().matrix_value ()); - double wmax = ext(0)+4, hmax = ext(1), angle = 0; + double wmax = ext(0)+4; + double hmax = ext(1); + double angle = 0; ColumnVector p = graphics_xform::xform_vector (xpTick, (ypTickN+ypTick)/2, zpTick); @@ -5333,7 +5375,9 @@ get_zticklabel ().all_strings (), get_zlim ().matrix_value ()); - double wmax = ext(0), hmax = ext(1), angle = 0; + double wmax = ext(0); + double hmax = ext(1); + double angle = 0; ColumnVector p; if (xySym) @@ -6402,7 +6446,8 @@ #endif Matrix ext (1, 2, 0.0); - double wmax = 0., hmax = 0.; + double wmax, hmax; + wmax = hmax = 0.; int n = std::min (ticklabels.numel (), ticks.numel ()); for (int i = 0; i < n; i++) { @@ -6878,14 +6923,14 @@ } inline -double force_in_range (const double x, const double lower, const double upper) +double force_in_range (double x, double lower, double upper) { if (x < lower) - { return lower; } + return lower; else if (x > upper) - { return upper; } + return upper; else - { return x; } + return x; } static Matrix @@ -7225,7 +7270,8 @@ { #ifdef HAVE_FREETYPE - int halign = 0, valign = 0; + int halign = 0; + int valign = 0; if (horizontalalignment_is ("center")) halign = 1; @@ -7368,9 +7414,11 @@ Matrix z = get_zdata ().matrix_value (); - int p = z.columns (), q = z.rows (); - int i1 = 0, i2 = 0, i3 = 0; - int j1 = 0, j2 = 0, j3 = 0; + int p = z.columns (); + int q = z.rows (); + int i1, i2, i3, j1, j2, j3; + i1 = i2 = i3 = 0; + j1 = j2 = j3 = 0; bool x_mat = (x.rows () == q); bool y_mat = (y.columns () == p); @@ -8144,9 +8192,9 @@ // No copying! - function_event (const function_event &); - - function_event & operator = (const function_event &); + function_event (const function_event&); + + function_event & operator = (const function_event&); }; class @@ -8348,7 +8396,7 @@ } void -gh_manager::do_post_callback (const graphics_handle& h, const std::string name, +gh_manager::do_post_callback (const graphics_handle& h, const std::string& name, const octave_value& data) { gh_manager::auto_lock guard; @@ -8398,7 +8446,7 @@ } void -gh_manager::do_post_set (const graphics_handle& h, const std::string name, +gh_manager::do_post_set (const graphics_handle& h, const std::string& name, const octave_value& value, bool notify_toolkit) { gh_manager::auto_lock guard; @@ -8706,6 +8754,29 @@ { obj.set (args(1).map_value ()); } + else if (nargin == 2 && args(1).is_string ()) + { + std::string property = args(1).string_value (); + + octave_map pmap = obj.values_as_struct (); + + if (pmap.isfield (property)) + { + if (nargout != 0) + retval = pmap.getfield (property)(0); + else + { + std::string s = obj.value_as_string (property); + if (! error_state) + octave_stdout << s; + } + } + else + { + error ("set: unknown property"); + break; + } + } else if (nargin == 1) { if (nargout != 0) @@ -8748,7 +8819,7 @@ } static std::string -get_graphics_object_type (const double val) +get_graphics_object_type (double val) { std::string retval; @@ -9379,7 +9450,7 @@ { graphics_handle h = octave_NaN; - const NDArray vals = args (0).array_value (); + const NDArray vals = args(0).array_value (); if (! error_state) { @@ -10176,7 +10247,7 @@ static bool compare_property_values (const octave_value& o1, const octave_value& o2) { - octave_value_list args (2); + octave_value_list args(2); args(0) = o1; args(1) = o2; diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/graphics.in.h --- a/libinterp/corefcn/graphics.in.h Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/graphics.in.h Tue Jan 07 16:07:54 2014 -0500 @@ -296,7 +296,7 @@ graphics_handle get_parent (void) const { return parent; } - void set_parent (const graphics_handle &h) { parent = h; } + void set_parent (const graphics_handle& h) { parent = h; } bool is_hidden (void) const { return hidden; } @@ -1028,7 +1028,7 @@ validate (); } - color_values (std::string str) + color_values (const std::string& str) : xrgb (1, 3) { if (! str2rgb (str)) @@ -1076,7 +1076,7 @@ private: Matrix xrgb; - OCTINTERP_API bool str2rgb (std::string str); + OCTINTERP_API bool str2rgb (const std::string& str); }; class color_property : public base_property @@ -1631,7 +1631,7 @@ } children_property (const std::string& nm, const graphics_handle& h, - const Matrix &val) + const Matrix& val) : base_property (nm, h), children_list () { do_init_children (val); @@ -1651,12 +1651,12 @@ base_property* clone (void) const { return new children_property (*this); } - bool remove_child (const double &val) + bool remove_child (double val) { return do_remove_child (val); } - void adopt (const double &val) + void adopt (double val) { do_adopt_child (val); } @@ -1759,14 +1759,14 @@ } private: - void do_init_children (const Matrix &val) + void do_init_children (const Matrix& val) { children_list.clear (); for (octave_idx_type i = 0; i < val.numel (); i++) children_list.push_front (val.xelem (i)); } - void do_init_children (const std::list &val) + void do_init_children (const std::list& val) { children_list.clear (); for (const_children_list_iterator p = val.begin (); p != val.end (); p++) @@ -1800,7 +1800,7 @@ return false; } - void do_adopt_child (const double &val) + void do_adopt_child (double val) { children_list.push_front (val); } @@ -2600,7 +2600,7 @@ protected: struct cmp_caseless_str { - bool operator () (const caseless_str &a, const caseless_str &b) const + bool operator () (const caseless_str& a, const caseless_str& b) const { std::string a1 = a; std::transform (a1.begin (), a1.end (), a1.begin (), tolower); @@ -2706,6 +2706,8 @@ virtual std::string values_as_string (void); + virtual std::string value_as_string (const std::string& prop); + virtual octave_scalar_map values_as_struct (void); virtual graphics_handle get_parent (void) const @@ -2977,6 +2979,11 @@ std::string values_as_string (void) { return rep->values_as_string (); } + std::string value_as_string (const std::string& prop) + { + return rep->value_as_string (prop); + } + octave_map values_as_struct (void) { return rep->values_as_struct (); } graphics_handle get_parent (void) const { return rep->get_parent (); } @@ -5389,11 +5396,11 @@ // --------------------------------------------------------------------- octave_value -get_property_from_handle (double handle, const std::string &property, - const std::string &func); +get_property_from_handle (double handle, const std::string& property, + const std::string& func); bool -set_property_in_handle (double handle, const std::string &property, - const octave_value &arg, const std::string &func); +set_property_in_handle (double handle, const std::string& property, + const octave_value& arg, const std::string& func); // --------------------------------------------------------------------- @@ -5864,12 +5871,12 @@ void do_execute_callback (const graphics_handle& h, const octave_value& cb, const octave_value& data); - void do_post_callback (const graphics_handle& h, const std::string name, + void do_post_callback (const graphics_handle& h, const std::string& name, const octave_value& data); void do_post_function (graphics_event::event_fcn fcn, void* fcn_data); - void do_post_set (const graphics_handle& h, const std::string name, + void do_post_set (const graphics_handle& h, const std::string& name, const octave_value& value, bool notify_toolkit = true); int do_process_events (bool force = false); diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/help.cc --- a/libinterp/corefcn/help.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/help.cc Tue Jan 07 16:07:54 2014 -0500 @@ -1078,7 +1078,7 @@ if (args.length () == 1) { - const std::string name = args (0).string_value (); + const std::string name = args(0).string_value (); if (! error_state) { @@ -1367,7 +1367,7 @@ retval = Cell (ffl.append (afl)); else { - std::string dir = args (0).string_value (); + std::string dir = args(0).string_value (); if (! error_state) { diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/kron.cc --- a/libinterp/corefcn/kron.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/kron.cc Tue Jan 07 16:07:54 2014 -0500 @@ -55,8 +55,10 @@ assert (a.ndims () == 2); assert (b.ndims () == 2); - octave_idx_type nra = a.rows (), nrb = b.rows (); - octave_idx_type nca = a.cols (), ncb = b.cols (); + octave_idx_type nra = a.rows (); + octave_idx_type nrb = b.rows (); + octave_idx_type nca = a.cols (); + octave_idx_type ncb = b.cols (); MArray c (dim_vector (nra*nrb, nca*ncb)); T *cv = c.fortran_vec (); @@ -79,8 +81,11 @@ { assert (b.ndims () == 2); - octave_idx_type nra = a.rows (), nrb = b.rows (), dla = a.diag_length (); - octave_idx_type nca = a.cols (), ncb = b.cols (); + octave_idx_type nra = a.rows (); + octave_idx_type nrb = b.rows (); + octave_idx_type dla = a.diag_length (); + octave_idx_type nca = a.cols (); + octave_idx_type ncb = b.cols (); MArray c (dim_vector (nra*nrb, nca*ncb), T ()); @@ -129,12 +134,15 @@ static PermMatrix kron (const PermMatrix& a, const PermMatrix& b) { - octave_idx_type na = a.rows (), nb = b.rows (); - const octave_idx_type *pa = a.data (), *pb = b.data (); + octave_idx_type na = a.rows (); + octave_idx_type nb = b.rows (); + const octave_idx_type *pa = a.data (); + const octave_idx_type *pb = b.data (); PermMatrix c(na*nb); // Row permutation. octave_idx_type *pc = c.fortran_vec (); - bool cola = a.is_col_perm (), colb = b.is_col_perm (); + bool cola = a.is_col_perm (); + bool colb = b.is_col_perm (); if (cola && colb) { for (octave_idx_type i = 0; i < na; i++) @@ -282,7 +290,8 @@ if (nargin >= 2) { - octave_value a = args(0), b = args(1); + octave_value a = args(0); + octave_value b = args(1); retval = dispatch_kron (a, b); for (octave_idx_type i = 2; i < nargin; i++) retval = dispatch_kron (retval, args(i)); diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/load-path.cc --- a/libinterp/corefcn/load-path.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/load-path.cc Tue Jan 07 16:07:54 2014 -0500 @@ -38,6 +38,7 @@ #include "defun.h" #include "input.h" #include "load-path.h" +#include "ov-usr-fcn.h" #include "pager.h" #include "parse.h" #include "toplev.h" @@ -120,6 +121,7 @@ if (fs) { method_file_map.clear (); + package_dir_map.clear (); dir_mtime = fs.mtime (); dir_time_last_checked = octave_time (); @@ -181,6 +183,8 @@ get_private_file_map (full_name); else if (fname[0] == '@') get_method_file_map (full_name, fname.substr (1)); + else if (fname[0] == '+') + get_package_dir (full_name, fname.substr (1)); } else { @@ -286,6 +290,13 @@ method_file_map[class_name].private_file_map = get_fcn_files (pd); } +void +load_path::dir_info::get_package_dir (const std::string& d, + const std::string& package_name) +{ + package_dir_map[package_name] = dir_info (d); +} + bool load_path::instance_ok (void) { @@ -373,8 +384,8 @@ } void -load_path::move_fcn_map (const std::string& dir_name, - const string_vector& fcn_files, bool at_end) +load_path::loader::move_fcn_map (const std::string& dir_name, + const string_vector& fcn_files, bool at_end) { octave_idx_type len = fcn_files.length (); @@ -422,7 +433,7 @@ } void -load_path::move_method_map (const std::string& dir_name, bool at_end) +load_path::loader::move_method_map (const std::string& dir_name, bool at_end) { for (method_map_iterator i = method_map.begin (); i != method_map.end (); @@ -466,7 +477,7 @@ } void -load_path::move (dir_info_list_iterator i, bool at_end) +load_path::do_move (dir_info_list_iterator i, bool at_end) { if (dir_info_list.size () > 1) { @@ -479,16 +490,56 @@ else dir_info_list.push_front (di); - std::string dir_name = di.dir_name; - - move_fcn_map (dir_name, di.fcn_files, at_end); - - // No need to move elements of private function map. - - move_method_map (dir_name, at_end); + move (di, at_end); + } +} + +void +load_path::move (const dir_info& di, bool at_end, const std::string& pname) +{ + loader& l = get_loader (pname); + + l.move (di, at_end); + + dir_info::package_dir_map_type package_dir_map = di.package_dir_map; + + for (dir_info::const_package_dir_map_iterator p = package_dir_map.begin (); + p != package_dir_map.end (); ++p) + { + std::string full_name = p->first; + + if (! pname.empty ()) + full_name = pname + "." + full_name; + + move (p->second, at_end, full_name); } } +void +load_path::loader::move (const dir_info& di, bool at_end) +{ + std::string dir_name = di.dir_name; + + std::list::iterator s = + std::find (dir_list.begin (), dir_list.end (), dir_name); + + if (s != dir_list.end ()) + { + dir_list.erase (s); + + if (at_end) + dir_list.push_back (dir_name); + else + dir_list.push_front (dir_name); + } + + move_fcn_map (dir_name, di.fcn_files, at_end); + + // No need to move elements of private function map. + + move_method_map (dir_name, at_end); +} + static void maybe_add_path_elts (std::string& path, const std::string& dir) { @@ -544,9 +595,10 @@ load_path::do_clear (void) { dir_info_list.clear (); - fcn_map.clear (); - private_fcn_map.clear (); - method_map.clear (); + + default_loader.clear (); + + loader_map.clear (); } static std::list @@ -683,7 +735,7 @@ dir_info_list_iterator i = find_dir_info (dir); if (i != dir_info_list.end ()) - move (i, at_end); + do_move (i, at_end); else { file_stat fs (dir); @@ -701,11 +753,7 @@ else dir_info_list.push_front (di); - add_to_fcn_map (di, at_end); - - add_to_private_fcn_map (di); - - add_to_method_map (di, at_end); + add (di, at_end); if (add_hook) add_hook (dir); @@ -726,12 +774,12 @@ i = find_dir_info ("."); if (i != dir_info_list.end ()) - move (i, false); + do_move (i, false); } void -load_path::remove_fcn_map (const std::string& dir, - const string_vector& fcn_files) +load_path::loader::remove_fcn_map (const std::string& dir, + const string_vector& fcn_files) { octave_idx_type len = fcn_files.length (); @@ -770,7 +818,7 @@ } void -load_path::remove_private_fcn_map (const std::string& dir) +load_path::loader::remove_private_fcn_map (const std::string& dir) { private_fcn_map_iterator p = private_fcn_map.find (dir); @@ -779,7 +827,7 @@ } void -load_path::remove_method_map (const std::string& dir) +load_path::loader::remove_method_map (const std::string& dir) { for (method_map_iterator i = method_map.begin (); i != method_map.end (); @@ -847,15 +895,11 @@ if (remove_hook) remove_hook (dir); - string_vector fcn_files = i->fcn_files; + dir_info& di = *i; + + remove (di); dir_info_list.erase (i); - - remove_fcn_map (dir, fcn_files); - - remove_private_fcn_map (dir); - - remove_method_map (dir); } } } @@ -864,17 +908,52 @@ } void +load_path::remove (const dir_info& di, const std::string& pname) +{ + loader& l = get_loader (pname); + + l.remove (di); + + dir_info::package_dir_map_type package_dir_map = di.package_dir_map; + + for (dir_info::const_package_dir_map_iterator p = package_dir_map.begin (); + p != package_dir_map.end (); ++p) + { + std::string full_name = p->first; + + if (! pname.empty ()) + full_name = pname + "." + full_name; + + remove (p->second, full_name); + } +} + +void +load_path::loader::remove (const dir_info& di) +{ + std::string dir = di.dir_name; + + string_vector fcn_files = di.fcn_files; + + dir_list.remove (dir); + + remove_fcn_map (dir, fcn_files); + + remove_private_fcn_map (dir); + + remove_method_map (dir); +} + +void load_path::do_update (void) const { // I don't see a better way to do this because we need to // preserve the correct directory ordering for new files that // have appeared. - fcn_map.clear (); - - private_fcn_map.clear (); - - method_map.clear (); + default_loader.clear (); + + loader_map.clear (); for (dir_info_list_iterator p = dir_info_list.begin (); p != dir_info_list.end (); @@ -884,11 +963,7 @@ di.update (); - add_to_fcn_map (di, true); - - add_to_private_fcn_map (di); - - add_to_method_map (di, true); + add (di, true); } } @@ -987,8 +1062,8 @@ } std::string -load_path::do_find_fcn (const std::string& fcn, std::string& dir_name, - int type) const +load_path::loader::find_fcn (const std::string& fcn, std::string& dir_name, + int type) const { std::string retval; @@ -1003,7 +1078,7 @@ std::string class_name = fcn.substr (1, pos-1); std::string meth = fcn.substr (pos+1); - retval = do_find_method (class_name, meth, dir_name); + retval = find_method (class_name, meth, dir_name); } else retval = std::string (); @@ -1042,8 +1117,8 @@ } std::string -load_path::do_find_private_fcn (const std::string& dir, - const std::string& fcn, int type) const +load_path::loader::find_private_fcn (const std::string& dir, + const std::string& fcn, int type) const { std::string retval; @@ -1072,9 +1147,9 @@ } std::string -load_path::do_find_method (const std::string& class_name, - const std::string& meth, - std::string& dir_name, int type) const +load_path::loader::find_method (const std::string& class_name, + const std::string& meth, + std::string& dir_name, int type) const { std::string retval; @@ -1120,7 +1195,7 @@ } std::list -load_path::do_methods (const std::string& class_name) const +load_path::loader::methods (const std::string& class_name) const { std::list retval; @@ -1149,13 +1224,63 @@ // update (); + default_loader.overloads (meth, retval); + + for (const_loader_map_iterator l = loader_map.begin (); + l != loader_map.end (); ++l) + l->second.overloads (meth, retval); + + return retval; +} + +void +load_path::loader::overloads (const std::string& meth, + std::list& l) const +{ for (const_method_map_iterator q = method_map.begin (); q != method_map.end (); q++) { const fcn_map_type& m = q->second; if (m.find (meth) != m.end ()) - retval.push_back (q->first); + { + std::string class_name = q->first; + + if (! prefix.empty ()) + class_name = prefix + "." + class_name; + + l.push_back (class_name); + } + } +} + +// Should we cache all files in private directories, or is it OK to just +// look them up each time as needed? + +std::string +find_private_file (const std::string& fname) +{ + std::string retval; + + // Look in private directory corresponding to current function (if + // any). + + octave_user_function *curr_fcn = symbol_table::get_curr_fcn (); + + if (curr_fcn && ! curr_fcn->is_private_function ()) + { + std::string dir_name = curr_fcn->dir_name (); + + if (! dir_name.empty ()) + { + std::string pfname = dir_name + file_ops::dir_sep_str () + + "private" + file_ops::dir_sep_str () + fname; + + file_stat fs (pfname); + + if (fs.exists () && fs.is_reg ()) + retval = pfname; + } } return retval; @@ -1166,33 +1291,43 @@ { std::string retval; + if (octave_env::absolute_pathname (file) + || octave_env::rooted_relative_pathname (file)) + { + file_stat fs (file); + + if (fs.exists ()) + return file; + } + else + { + std::string tfile = find_private_file (file); + + if (! tfile.empty ()) + return tfile; + } + if (file.find_first_of (file_ops::dir_sep_chars ()) != std::string::npos) { - if (octave_env::absolute_pathname (file) - || octave_env::rooted_relative_pathname (file)) + // Given name has a directory separator, so append it to each + // element of the load path in turn. + + for (const_dir_info_list_iterator p = dir_info_list.begin (); + p != dir_info_list.end (); + p++) { - file_stat fs (file); + std::string tfile = file_ops::concat (p->dir_name, file); + + file_stat fs (tfile); if (fs.exists ()) - return file; - } - else - { - for (const_dir_info_list_iterator p = dir_info_list.begin (); - p != dir_info_list.end (); - p++) - { - std::string tfile = file_ops::concat (p->dir_name, file); - - file_stat fs (tfile); - - if (fs.exists ()) - return tfile; - } + return tfile; } } else { + // Look in cache. + for (const_dir_info_list_iterator p = dir_info_list.begin (); p != dir_info_list.end (); p++) @@ -1515,6 +1650,12 @@ string_vector load_path::do_fcn_names (void) const { + return default_loader.fcn_names (); +} + +string_vector +load_path::loader::fcn_names (void) const +{ size_t len = fcn_map.size (); string_vector retval (len); @@ -1657,69 +1798,11 @@ } } - for (const_private_fcn_map_iterator i = private_fcn_map.begin (); - i != private_fcn_map.end (); i++) - { - os << "\n*** private functions in " - << file_ops::concat (i->first, "private") << ":\n\n"; - - print_fcn_list (os, i->second); - } - -#if defined (DEBUG_LOAD_PATH) - - for (const_fcn_map_iterator i = fcn_map.begin (); - i != fcn_map.end (); - i++) - { - os << i->first << ":\n"; - - const file_info_list_type& file_info_list = i->second; - - for (const_file_info_list_iterator p = file_info_list.begin (); - p != file_info_list.end (); - p++) - { - os << " " << p->dir_name << " ("; - - print_types (os, p->types); - - os << ")\n"; - } - } - - for (const_method_map_iterator i = method_map.begin (); - i != method_map.end (); - i++) - { - os << "CLASS " << i->first << ":\n"; - - const fcn_map_type& fm = i->second; - - for (const_fcn_map_iterator q = fm.begin (); - q != fm.end (); - q++) - { - os << " " << q->first << ":\n"; - - const file_info_list_type& file_info_list = q->second; - - for (const_file_info_list_iterator p = file_info_list.begin (); - p != file_info_list.end (); - p++) - { - os << " " << p->dir_name << " ("; - - print_types (os, p->types); - - os << ")\n"; - } - } - } - - os << "\n"; - -#endif + default_loader.display (os); + + for (const_loader_map_iterator l = loader_map.begin (); + l != loader_map.end (); ++l) + l->second.display (os); } // True if a path is contained in a path list separated by path_sep_char @@ -1743,7 +1826,29 @@ } void -load_path::add_to_fcn_map (const dir_info& di, bool at_end) const +load_path::add (const dir_info& di, bool at_end, + const std::string& pname) const +{ + loader& l = get_loader (pname); + + l.add (di, at_end); + + dir_info::package_dir_map_type package_dir_map = di.package_dir_map; + + for (dir_info::const_package_dir_map_iterator p = package_dir_map.begin (); + p != package_dir_map.end (); ++p) + { + std::string full_name = p->first; + + if (! pname.empty ()) + full_name = pname + "." + full_name; + + add (p->second, at_end, full_name); + } +} + +void +load_path::loader::add_to_fcn_map (const dir_info& di, bool at_end) { std::string dir_name = di.dir_name; @@ -1839,7 +1944,7 @@ } void -load_path::add_to_private_fcn_map (const dir_info& di) const +load_path::loader::add_to_private_fcn_map (const dir_info& di) { dir_info::fcn_file_map_type private_file_map = di.private_file_map; @@ -1848,7 +1953,7 @@ } void -load_path::add_to_method_map (const dir_info& di, bool at_end) const +load_path::loader::add_to_method_map (const dir_info& di, bool at_end) { std::string dir_name = di.dir_name; @@ -1918,6 +2023,81 @@ } } +void +load_path::loader::display (std::ostream& os) const +{ + os << "*** loader: " << (prefix.empty () ? "" : prefix) << "\n\n"; + + for (std::list::const_iterator s = dir_list.begin (); + s != dir_list.end (); ++s) + os << *s << "\n"; + os << "\n"; + + for (const_private_fcn_map_iterator i = private_fcn_map.begin (); + i != private_fcn_map.end (); i++) + { + os << "\n*** private functions in " + << file_ops::concat (i->first, "private") << ":\n\n"; + + print_fcn_list (os, i->second); + } + +#if defined (DEBUG_LOAD_PATH) + + for (const_fcn_map_iterator i = fcn_map.begin (); + i != fcn_map.end (); + i++) + { + os << i->first << ":\n"; + + const file_info_list_type& file_info_list = i->second; + + for (const_file_info_list_iterator p = file_info_list.begin (); + p != file_info_list.end (); + p++) + { + os << " " << p->dir_name << " ("; + + print_types (os, p->types); + + os << ")\n"; + } + } + + for (const_method_map_iterator i = method_map.begin (); + i != method_map.end (); + i++) + { + os << "CLASS " << i->first << ":\n"; + + const fcn_map_type& fm = i->second; + + for (const_fcn_map_iterator q = fm.begin (); + q != fm.end (); + q++) + { + os << " " << q->first << ":\n"; + + const file_info_list_type& file_info_list = q->second; + + for (const_file_info_list_iterator p = file_info_list.begin (); + p != file_info_list.end (); + p++) + { + os << " " << p->dir_name << " ("; + + print_types (os, p->types); + + os << ")\n"; + } + } + } + + os << "\n"; + +#endif +} + std::string genpath (const std::string& dirname, const string_vector& skip) { @@ -1929,7 +2109,7 @@ { retval = dirname; - string_vector dirlist = dir.read (); + string_vector dirlist = dir.read ().sort (false); octave_idx_type len = dirlist.length (); @@ -1937,7 +2117,8 @@ { std::string elt = dirlist[i]; - bool skip_p = (elt == "." || elt == ".." || elt[0] == '@'); + bool skip_p = (elt == "." || elt == ".." || elt[0] == '@' + || elt[0] == '+'); if (! skip_p) { @@ -1964,6 +2145,21 @@ return retval; } +std::list +load_path::do_get_all_package_names (bool only_top_level) const +{ + std::list retval; + + for (const_loader_map_iterator l = loader_map.begin (); + l != loader_map.end (); ++l) + { + if (! only_top_level || l->first.find ('.') == std::string::npos) + retval.push_back (l->first); + } + + return retval; +} + static void execute_pkg_add_or_del (const std::string& dir, const std::string& script_file) @@ -2339,3 +2535,10 @@ return retval; } + +DEFUN (__dump_load_path__, , , "") +{ + load_path::display (octave_stdout); + + return octave_value_list (); +} diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/load-path.h --- a/libinterp/corefcn/load-path.h Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/load-path.h Tue Jan 07 16:07:54 2014 -0500 @@ -39,8 +39,7 @@ protected: load_path (void) - : dir_info_list (), fcn_map (), private_fcn_map (), method_map (), - init_dirs () { } + : loader_map (), default_loader (), dir_info_list (), init_dirs () { } public: @@ -96,24 +95,29 @@ static std::string find_method (const std::string& class_name, const std::string& meth, - std::string& dir_name) + std::string& dir_name, + const std::string& pack_name = std::string ()) { return instance_ok () - ? instance->do_find_method (class_name, meth, dir_name) - : std::string (); + ? instance->get_loader (pack_name).find_method (class_name, meth, + dir_name) + : std::string (); } static std::string find_method (const std::string& class_name, - const std::string& meth) + const std::string& meth, + const std::string& pack_name = std::string ()) { std::string dir_name; - return find_method (class_name, meth, dir_name); + return find_method (class_name, meth, dir_name, pack_name); } - static std::list methods (const std::string& class_name) + static std::list methods (const std::string& class_name, + const std::string& pack_name = std::string ()) { return instance_ok () - ? instance->do_methods (class_name) : std::list (); + ? instance->get_loader(pack_name).methods (class_name) + : std::list (); } static std::list overloads (const std::string& meth) @@ -122,47 +126,72 @@ ? instance->do_overloads (meth) : std::list (); } - static std::string find_fcn (const std::string& fcn, std::string& dir_name) + static bool find_package (const std::string& package_name) + { + return instance_ok () + ? instance->do_find_package (package_name) : false; + } + + static std::list + get_all_package_names (bool only_top_level = true) { return instance_ok () - ? instance->do_find_fcn (fcn, dir_name) : std::string (); + ? instance->do_get_all_package_names (only_top_level) + : std::list (); } - static std::string find_fcn (const std::string& fcn) + static std::string find_fcn (const std::string& fcn, std::string& dir_name, + const std::string& pack_name = std::string ()) + { + return instance_ok () + ? instance->get_loader (pack_name).find_fcn (fcn, dir_name) + : std::string (); + } + + static std::string find_fcn (const std::string& fcn, + const std::string& pack_name = std::string ()) { std::string dir_name; - return find_fcn (fcn, dir_name); + return find_fcn (fcn, dir_name, pack_name); } static std::string find_private_fcn (const std::string& dir, - const std::string& fcn) + const std::string& fcn, + const std::string& pack_name = std::string ()) { return instance_ok () - ? instance->do_find_private_fcn (dir, fcn) : std::string (); + ? instance->get_loader (pack_name).find_private_fcn (dir, fcn) + : std::string (); } - static std::string find_fcn_file (const std::string& fcn) + static std::string find_fcn_file (const std::string& fcn, + const std::string& pack_name = std::string ()) { std::string dir_name; - return instance_ok () ? - instance->do_find_fcn (fcn, dir_name, M_FILE) : std::string (); + return instance_ok () + ? instance->get_loader (pack_name).find_fcn (fcn, dir_name, M_FILE) + : std::string (); } - static std::string find_oct_file (const std::string& fcn) + static std::string find_oct_file (const std::string& fcn, + const std::string& pack_name = std::string ()) { std::string dir_name; - return instance_ok () ? - instance->do_find_fcn (fcn, dir_name, OCT_FILE) : std::string (); + return instance_ok () + ? instance->get_loader (pack_name).find_fcn (fcn, dir_name, M_FILE) + : std::string (); } - static std::string find_mex_file (const std::string& fcn) + static std::string find_mex_file (const std::string& fcn, + const std::string& pack_name = std::string ()) { std::string dir_name; - return instance_ok () ? - instance->do_find_fcn (fcn, dir_name, MEX_FILE) : std::string (); + return instance_ok () + ? instance->get_loader (pack_name).find_fcn (fcn, dir_name, M_FILE) + : std::string (); } static std::string find_file (const std::string& file) @@ -297,19 +326,27 @@ typedef method_file_map_type::const_iterator const_method_file_map_iterator; typedef method_file_map_type::iterator method_file_map_iterator; + // + typedef std::map package_dir_map_type; + + typedef package_dir_map_type::const_iterator const_package_dir_map_iterator; + typedef package_dir_map_type::iterator package_dir_map_iterator; + // This default constructor is only provided so we can create a // std::map of dir_info objects. You should not use this // constructor for any other purpose. dir_info (void) : dir_name (), abs_dir_name (), is_relative (false), dir_mtime (), dir_time_last_checked (), - all_files (), fcn_files (), private_file_map (), method_file_map () + all_files (), fcn_files (), private_file_map (), method_file_map (), + package_dir_map () { } dir_info (const std::string& d) : dir_name (d), abs_dir_name (), is_relative (false), dir_mtime (), dir_time_last_checked (), - all_files (), fcn_files (), private_file_map (), method_file_map () + all_files (), fcn_files (), private_file_map (), method_file_map (), + package_dir_map () { initialize (); } @@ -321,7 +358,8 @@ dir_time_last_checked (di.dir_time_last_checked), all_files (di.all_files), fcn_files (di.fcn_files), private_file_map (di.private_file_map), - method_file_map (di.method_file_map) { } + method_file_map (di.method_file_map), + package_dir_map (di.package_dir_map) { } ~dir_info (void) { } @@ -338,6 +376,7 @@ fcn_files = di.fcn_files; private_file_map = di.private_file_map; method_file_map = di.method_file_map; + package_dir_map = di.package_dir_map; } return *this; @@ -354,6 +393,7 @@ string_vector fcn_files; fcn_file_map_type private_file_map; method_file_map_type method_file_map; + package_dir_map_type package_dir_map; private: @@ -366,6 +406,9 @@ void get_method_file_map (const std::string& d, const std::string& class_name); + void get_package_dir (const std::string& d, + const std::string& package_name); + friend fcn_file_map_type get_fcn_files (const std::string& d); }; @@ -442,13 +485,125 @@ typedef method_map_type::const_iterator const_method_map_iterator; typedef method_map_type::iterator method_map_iterator; - mutable dir_info_list_type dir_info_list; + class loader + { + public: + loader (const std::string& pfx = std::string ()) + : prefix (pfx), dir_list (), fcn_map (), private_fcn_map (), + method_map () { } + + loader (const loader& l) + : prefix (l.prefix), dir_list (l.dir_list), + private_fcn_map (l.private_fcn_map), method_map (l.method_map) { } + + ~loader (void) { } + + loader& operator = (const loader& l) + { + if (&l != this) + { + prefix = l.prefix; + dir_list = l.dir_list; + fcn_map = l.fcn_map; + private_fcn_map = l.private_fcn_map; + method_map = l.method_map; + } + + return *this; + } - mutable fcn_map_type fcn_map; + void add (const dir_info& di, bool at_end) + { + if (at_end) + dir_list.push_back (di.dir_name); + else + dir_list.push_front (di.dir_name); + + add_to_fcn_map (di, at_end); + + add_to_private_fcn_map (di); + + add_to_method_map (di, at_end); + } + + void move (const dir_info& di, bool at_end); + + void remove (const dir_info& di); + + void clear (void) + { + dir_list.clear (); + + fcn_map.clear (); + + private_fcn_map.clear (); + + method_map.clear (); + } + + void display (std::ostream& out) const; - mutable private_fcn_map_type private_fcn_map; + std::string find_fcn (const std::string& fcn, + std::string& dir_name, + int type = M_FILE | OCT_FILE | MEX_FILE) const; + + std::string find_private_fcn (const std::string& dir, + const std::string& fcn, + int type = M_FILE | OCT_FILE | MEX_FILE) const; + + std::string find_method (const std::string& class_name, + const std::string& meth, + std::string& dir_name, + int type = M_FILE | OCT_FILE | MEX_FILE) const; + + std::list methods (const std::string& class_name) const; + + void overloads (const std::string& meth, std::list& l) const; + + string_vector fcn_names (void) const; + + private: + void add_to_fcn_map (const dir_info& di, bool at_end); + + void add_to_private_fcn_map (const dir_info& di); + + void add_to_method_map (const dir_info& di, bool at_end); + + void move_fcn_map (const std::string& dir, + const string_vector& fcn_files, bool at_end); + + void move_method_map (const std::string& dir, bool at_end); - mutable method_map_type method_map; + void remove_fcn_map (const std::string& dir, + const string_vector& fcn_files); + + void remove_private_fcn_map (const std::string& dir); + + void remove_method_map (const std::string& dir); + + private: + std::string prefix; + + std::list dir_list; + + fcn_map_type fcn_map; + + private_fcn_map_type private_fcn_map; + + method_map_type method_map; + }; + + // + typedef std::map loader_map_type; + + typedef loader_map_type::const_iterator const_loader_map_iterator; + typedef loader_map_type::iterator loader_map_iterator; + + mutable loader_map_type loader_map; + + mutable loader default_loader; + + mutable dir_info_list_type dir_info_list; mutable std::set init_dirs; @@ -475,12 +630,13 @@ bool do_contains_canonical (const std::string& dir) const; - void move_fcn_map (const std::string& dir, - const string_vector& fcn_files, bool at_end); + void do_move (dir_info_list_iterator i, bool at_end); - void move_method_map (const std::string& dir, bool at_end); + void move (const dir_info& di, bool at_end, + const std::string& pname = std::string ()); - void move (std::list::iterator i, bool at_end); + void remove (const dir_info& di, + const std::string& pname = std::string ()); void do_initialize (bool set_initial_path); @@ -494,12 +650,6 @@ void do_add (const std::string& dir, bool at_end, bool warn); - void remove_fcn_map (const std::string& dir, const string_vector& fcn_files); - - void remove_private_fcn_map (const std::string& dir); - - void remove_method_map (const std::string& dir); - bool do_remove (const std::string& dir); void do_update (void) const; @@ -508,23 +658,31 @@ check_file_type (std::string& fname, int type, int possible_types, const std::string& fcn, const char *who); - std::string do_find_fcn (const std::string& fcn, - std::string& dir_name, - int type = M_FILE | OCT_FILE | MEX_FILE) const; + loader& get_loader (const std::string& name) const + { + if (! name.empty ()) + { + loader_map_iterator l = loader_map.find (name); - std::string do_find_private_fcn (const std::string& dir, - const std::string& fcn, - int type = M_FILE | OCT_FILE | MEX_FILE) const; + if (l == loader_map.end ()) + l = loader_map.insert (loader_map.end (), + loader_map_type::value_type (name, loader (name))); - std::string do_find_method (const std::string& class_name, - const std::string& meth, - std::string& dir_name, - int type = M_FILE | OCT_FILE | MEX_FILE) const; + return l->second; + } - std::list do_methods (const std::string& class_name) const; + return default_loader; + } std::list do_overloads (const std::string& meth) const; + bool do_find_package (const std::string& package_name) const + { + return (loader_map.find (package_name) != loader_map.end ()); + } + + std::list do_get_all_package_names (bool only_top_level) const; + std::string do_find_file (const std::string& file) const; std::string do_find_dir (const std::string& dir) const; @@ -559,11 +717,8 @@ std::string do_get_command_line_path (void) const { return command_line_path; } - void add_to_fcn_map (const dir_info& di, bool at_end) const; - - void add_to_private_fcn_map (const dir_info& di) const; - - void add_to_method_map (const dir_info& di, bool at_end) const; + void add (const dir_info& di, bool at_end, + const std::string& pname = std::string ()) const; friend dir_info::fcn_file_map_type get_fcn_files (const std::string& d); }; diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/load-save.cc --- a/libinterp/corefcn/load-save.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/load-save.cc Tue Jan 07 16:07:54 2014 -0500 @@ -502,17 +502,24 @@ if (! (octave_env::absolute_pathname (fname) || octave_env::rooted_relative_pathname (fname))) { + // Load path will also search "." first, but we don't want to + // issue a warning if the file is found in the current directory, + // so do an explicit check for that. + file_stat fs (fname); if (! (fs.exists () && fs.is_reg ())) { + // Not directly found; search load path. + std::string tmp = octave_env::make_absolute (load_path::find_file (fname)); if (! tmp.empty ()) { warning_with_id ("Octave:load-file-in-path", - "load: file found in load path"); + "load: file found in load path: %s", + tmp.c_str ()); fname = tmp; } } @@ -1065,7 +1072,8 @@ string_vector retval; int argc = argv.length (); - bool do_double = false, do_tabs = false; + bool do_double = false; + bool do_tabs = false; for (int i = 0; i < argc; i++) { diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/lookup.cc --- a/libinterp/corefcn/lookup.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/lookup.cc Tue Jan 07 16:07:54 2014 -0500 @@ -115,7 +115,8 @@ octave_value retval; Array idx = array.lookup (values); - octave_idx_type n = array.numel (), nval = values.numel (); + octave_idx_type n = array.numel (); + octave_idx_type nval = values.numel (); // Post-process. if (match_bool) @@ -246,7 +247,8 @@ return retval; } - octave_value table = args(0), y = args(1); + octave_value table = args(0); + octave_value y = args(1); if (table.ndims () > 2 || (table.columns () > 1 && table.rows () > 1)) warning ("lookup: table is not a vector"); diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/ls-hdf5.cc --- a/libinterp/corefcn/ls-hdf5.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/ls-hdf5.cc Tue Jan 07 16:07:54 2014 -0500 @@ -738,7 +738,8 @@ hsize_t sz = d.length (); OCTAVE_LOCAL_BUFFER (octave_idx_type, dims, sz); bool empty = false; - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid = -1; + hid_t data_hid = -1; int retval; for (hsize_t i = 0; i < sz; i++) { @@ -865,7 +866,9 @@ bool mark_as_global, bool save_as_floats) { hsize_t dims[3]; - hid_t type_id = -1, space_id = -1, data_id = -1, data_type_id = -1; + hid_t type_id, space_id, data_id, data_type_id; + type_id = space_id = data_id = data_type_id = -1; + bool retval = false; octave_value val = tc; // FIXME: diagonal & permutation matrices currently don't know how to save diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/ls-mat5.cc --- a/libinterp/corefcn/ls-mat5.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/ls-mat5.cc Tue Jan 07 16:07:54 2014 -0500 @@ -929,7 +929,7 @@ std::string dir_name = str.substr (0, xpos); octave_function *fcn - = load_fcn_from_file (str, dir_name, "", fname); + = load_fcn_from_file (str, dir_name, "", "", fname); if (fcn) { @@ -958,7 +958,7 @@ std::string dir_name = str.substr (0, xpos); octave_function *fcn - = load_fcn_from_file (str, dir_name, "", fname); + = load_fcn_from_file (str, dir_name, "", "", fname); if (fcn) { @@ -983,7 +983,7 @@ std::string dir_name = fpath.substr (0, xpos); octave_function *fcn - = load_fcn_from_file (fpath, dir_name, "", fname); + = load_fcn_from_file (fpath, dir_name, "", "", fname); if (fcn) { @@ -1560,7 +1560,8 @@ read_mat5_binary_file_header (std::istream& is, bool& swap, bool quiet, const std::string& filename) { - int16_t version=0, magic=0; + int16_t version = 0; + int16_t magic = 0; uint64_t subsys_offset; is.seekg (116, std::ios::beg); diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/lu.cc --- a/libinterp/corefcn/lu.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/lu.cc Tue Jan 07 16:07:54 2014 -0500 @@ -158,7 +158,7 @@ int n = 1; while (n < nargin && ! error_state) { - if (args (n).is_string ()) + if (args(n).is_string ()) { std::string tmp = args(n++).string_value (); @@ -588,7 +588,9 @@ bool check_lu_dims (const octave_value& l, const octave_value& u, const octave_value& p) { - octave_idx_type m = l.rows (), k = u.rows (), n = u.columns (); + octave_idx_type m = l.rows (); + octave_idx_type k = u.rows (); + octave_idx_type n = u.columns (); return ((l.ndims () == 2 && u.ndims () == 2 && k == l.columns ()) && k == std::min (m, n) && (p.is_undefined () || p.rows () == m)); diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/mappers.cc --- a/libinterp/corefcn/mappers.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/mappers.cc Tue Jan 07 16:07:54 2014 -0500 @@ -2156,8 +2156,17 @@ %!assert (tolower ({"ABC", "DEF", {"GHI", {"JKL"}}}), {"abc", "def", {"ghi", {"jkl"}}}) %!assert (tolower (["ABC"; "DEF"]), ["abc"; "def"]) %!assert (tolower ({["ABC"; "DEF"]}), {["abc";"def"]}) -%!assert (tolower (68), "d") -%!assert (tolower ({[68, 68; 68, 68]}), {["dd";"dd"]}) +%!assert (tolower (68), 68) +%!assert (tolower ({[68, 68; 68, 68]}), {[68, 68; 68, 68]}) +%!test +%! classes = {@char, @double, @single, ... +%! @int8, @int16, @int32, @int64, ... +%! @uint8, @uint16, @uint32, @uint64}; +%! for i = 1:numel (classes) +%! cls = classes{i}; +%! assert (class (tolower (cls (97))), class (cls (97))); +%! assert (class (tolower (cls ([98, 99]))), class (cls ([98, 99]))); +%! endfor %!test %! a(3,3,3,3) = "D"; %! assert (tolower (a)(3,3,3,3), "d"); @@ -2207,8 +2216,17 @@ %!assert (toupper ({"abc", "def", {"ghi", {"jkl"}}}), {"ABC", "DEF", {"GHI", {"JKL"}}}) %!assert (toupper (["abc"; "def"]), ["ABC"; "DEF"]) %!assert (toupper ({["abc"; "def"]}), {["ABC";"DEF"]}) -%!assert (toupper (100), "D") -%!assert (toupper ({[100, 100; 100, 100]}), {["DD";"DD"]}) +%!assert (toupper (100), 100) +%!assert (toupper ({[100, 100; 100, 100]}), {[100, 100; 100, 100]}) +%!test +%! classes = {@char, @double, @single, ... +%! @int8, @int16, @int32, @int64, ... +%! @uint8, @uint16, @uint32, @uint64}; +%! for i = 1:numel (classes) +%! cls = classes{i}; +%! assert (class (toupper (cls (97))), class (cls (97))); +%! assert (class (toupper (cls ([98, 99]))), class (cls ([98, 99]))); +%! endfor %!test %! a(3,3,3,3) = "d"; %! assert (toupper (a)(3,3,3,3), "D"); diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/matrix_type.cc --- a/libinterp/corefcn/matrix_type.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/matrix_type.cc Tue Jan 07 16:07:54 2014 -0500 @@ -281,7 +281,7 @@ && (str_typ == "upper" || str_typ == "lower")) { const ColumnVector perm = - ColumnVector (args (2).vector_value ()); + ColumnVector (args(2).vector_value ()); if (error_state) error ("matrix_type: Invalid permutation vector PERM"); @@ -454,7 +454,7 @@ || str_typ == "lower")) { const ColumnVector perm = - ColumnVector (args (2).vector_value ()); + ColumnVector (args(2).vector_value ()); if (error_state) error ("matrix_type: Invalid permutation vector PERM"); diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/max.cc --- a/libinterp/corefcn/max.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/max.cc Tue Jan 07 16:07:54 2014 -0500 @@ -354,8 +354,10 @@ } else if (nargin == 2) { - octave_value argx = args(0), argy = args(1); - builtin_type_t xtyp = argx.builtin_type (), ytyp = argy.builtin_type (); + octave_value argx = args(0); + octave_value argy = args(1); + builtin_type_t xtyp = argx.builtin_type (); + builtin_type_t ytyp = argy.builtin_type (); builtin_type_t rtyp; if (xtyp == btyp_char && ytyp == btyp_char) rtyp = btyp_char; @@ -560,6 +562,10 @@ %! assert (ndims(i), 2); %! assert (i, [1, 1; 1, 1]); +## Test for bug #40743 +%!assert (max (zeros (1,0), ones (1,1)), zeros (1,0)) +%!assert (max (sparse (zeros (1,0)), sparse (ones (1,1))), sparse (zeros (1,0))) + %!error max () %!error max (1, 2, 3, 4) */ diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/oct-map.cc --- a/libinterp/corefcn/oct-map.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/oct-map.cc Tue Jan 07 16:07:54 2014 -0500 @@ -117,7 +117,8 @@ { bool retval = true; - iterator p = begin (), q = other.begin (); + iterator p = begin (); + iterator q = other.begin (); for (; p != end () && q != other.end (); p++, q++) { if (p->first == q->first) diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/oct-obj.cc --- a/libinterp/corefcn/oct-obj.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/oct-obj.cc Tue Jan 07 16:07:54 2014 -0500 @@ -35,7 +35,8 @@ octave_value_list::octave_value_list (const std::list& lst) { - octave_idx_type n = 0, nel = 0; + octave_idx_type n = 0; + octave_idx_type nel = 0; // Determine number. for (std::list::const_iterator p = lst.begin (); diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/oct-obj.h --- a/libinterp/corefcn/oct-obj.h Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/oct-obj.h Tue Jan 07 16:07:54 2014 -0500 @@ -107,10 +107,16 @@ octave_value_list slice (octave_idx_type offset, octave_idx_type len, bool tags = false) const { - octave_value_list retval (data.linear_slice (offset, offset + len)); + // linear_slice uses begin/end indices instead of offset and + // length. Avoid calling with upper bound out of range. + // linear_slice handles the case of len < 0. + + octave_value_list retval + = data.linear_slice (offset, std::min (offset + len, length ())); + if (tags && len > 0 && names.length () > 0) - retval.names = names.linear_slice (offset, - std::min (len, names.length ())); + retval.names = names.linear_slice (offset, std::min (offset + len, + names.length ())); return retval; } diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/oct-stream.cc --- a/libinterp/corefcn/oct-stream.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/oct-stream.cc Tue Jan 07 16:07:54 2014 -0500 @@ -1053,7 +1053,8 @@ { std::istream& is = *isp; - int c = 0, lastc = -1; + int c = 0; + int lastc = -1; cnt = 0; while (is && (c = is.get ()) != EOF) @@ -2357,15 +2358,15 @@ return retval; } -#define DO_DOUBLE_CONV(TQUAL) \ +#define DO_DOUBLE_CONV_1(TYPE) \ do \ { \ - if (val > std::numeric_limits::max () \ - || val < std::numeric_limits::min ()) \ + if (val > std::numeric_limits::max () \ + || val < std::numeric_limits::min ()) \ { \ std::string tfmt = fmt; \ \ - tfmt.replace (tfmt.rfind (elt->type), 1, ".f"); \ + tfmt.replace (tfmt.rfind (elt->type), 1, ".g"); \ \ if (elt->modifier == 'l') \ tfmt.replace (tfmt.rfind (elt->modifier), 1, ""); \ @@ -2375,7 +2376,17 @@ } \ else \ retval += do_printf_conv (os, fmt, nsa, sa_1, sa_2, \ - static_cast (val), who); \ + static_cast (val), who); \ + } \ + while (0) + +#define DO_DOUBLE_CONV(TQUAL) \ + do \ + { \ + if (elt->modifier == 'l') \ + DO_DOUBLE_CONV_1 (TQUAL long); \ + else \ + DO_DOUBLE_CONV_1 (TQUAL int); \ } \ while (0) @@ -2478,15 +2489,19 @@ const char *tval; if (xisinf (val)) - if (elt->flags.find ('+') != std::string::npos) - tval = (val < 0 ? "-Inf" : "+Inf"); - else - tval = (val < 0 ? "-Inf" : "Inf"); + { + if (elt->flags.find ('+') != std::string::npos) + tval = (val < 0 ? "-Inf" : "+Inf"); + else + tval = (val < 0 ? "-Inf" : "Inf"); + } else - if (elt->flags.find ('+') != std::string::npos) - tval = (lo_ieee_is_NA (val) ? "+NA" : "+NaN"); - else - tval = (lo_ieee_is_NA (val) ? "NA" : "NaN"); + { + if (elt->flags.find ('+') != std::string::npos) + tval = (lo_ieee_is_NA (val) ? "+NA" : "+NaN"); + else + tval = (lo_ieee_is_NA (val) ? "NA" : "NaN"); + } retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/pr-output.cc --- a/libinterp/corefcn/pr-output.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/pr-output.cc Tue Jan 07 16:07:54 2014 -0500 @@ -3542,7 +3542,7 @@ if (nargin == 2) { - int fid = octave_stream_list::get_file_number (args (0)); + int fid = octave_stream_list::get_file_number (args(0)); octave_stream os = octave_stream_list::lookup (fid, "fdisp"); diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/pt-jit.cc --- a/libinterp/corefcn/pt-jit.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/pt-jit.cc Tue Jan 07 16:07:54 2014 -0500 @@ -683,6 +683,12 @@ } void +jit_convert::visit_funcall (tree_funcall&) +{ + throw jit_fail_exception (); +} + +void jit_convert::visit_parameter_list (tree_parameter_list&) { throw jit_fail_exception (); diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/pt-jit.h --- a/libinterp/corefcn/pt-jit.h Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/pt-jit.h Tue Jan 07 16:07:54 2014 -0500 @@ -129,6 +129,8 @@ void visit_fcn_handle (tree_fcn_handle&); + void visit_funcall (tree_funcall&); + void visit_parameter_list (tree_parameter_list&); void visit_postfix_expression (tree_postfix_expression&); diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/sparse.cc --- a/libinterp/corefcn/sparse.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/sparse.cc Tue Jan 07 16:07:54 2014 -0500 @@ -113,7 +113,7 @@ if (nargin == 1) { - octave_value arg = args (0); + octave_value arg = args(0); if (arg.is_bool_type ()) retval = arg.sparse_bool_matrix_value (); else if (arg.is_complex_type ()) @@ -125,7 +125,8 @@ } else if (nargin == 2) { - octave_idx_type m = 0, n = 0; + octave_idx_type m = 0; + octave_idx_type n = 0; if (args(0).is_scalar_type () && args(1).is_scalar_type ()) { m = args(0).idx_type_value (); @@ -160,7 +161,8 @@ if (! error_state) { - octave_idx_type m = -1, n = -1, nzmax = -1; + octave_idx_type m, n, nzmax; + m = n = nzmax = -1; if (nargin == 6) { nzmax = args(5).idx_type_value (); diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/sqrtm.cc --- a/libinterp/corefcn/sqrtm.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/sqrtm.cc Tue Jan 07 16:07:54 2014 -0500 @@ -101,7 +101,8 @@ typedef typename Matrix::element_type real_type; - real_type cutoff = 0, one = 1; + real_type cutoff = 0; + real_type one = 1; real_type eps = std::numeric_limits::epsilon (); if (! iscomplex) diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/str2double.cc --- a/libinterp/corefcn/str2double.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/str2double.cc Tue Jan 07 16:07:54 2014 -0500 @@ -60,7 +60,8 @@ { // It's infinity. is.get (); - char c1 = is.get (), c2 = is.get (); + char c1 = is.get (); + char c2 = is.get (); if (std::tolower (c1) == 'n' && std::tolower (c2) == 'f') { num = octave_Inf; diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/strfind.cc --- a/libinterp/corefcn/strfind.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/strfind.cc Tue Jan 07 16:07:54 2014 -0500 @@ -209,7 +209,8 @@ if (nargin == 2) { - octave_value argstr = args(0), argpat = args(1); + octave_value argstr = args(0); + octave_value argpat = args(1); if (argpat.is_string ()) { Array needle = argpat.char_array_value (); @@ -279,7 +280,9 @@ { Array ret = str; - octave_idx_type siz = str.numel (), psiz = pat.numel (), rsiz = rep.numel (); + octave_idx_type siz = str.numel (); + octave_idx_type psiz = pat.numel (); + octave_idx_type rsiz = rep.numel (); if (psiz != 0) { @@ -312,7 +315,8 @@ retsiz = siz + nidx * (rsiz - psiz); ret.clear (dim_vector (1, retsiz)); - const char *src = str.data (), *reps = rep.data (); + const char *src = str.data (); + const char *reps = rep.data (); char *dest = ret.fortran_vec (); octave_idx_type k = 0; @@ -380,7 +384,9 @@ if (nargin == 3) { - octave_value argstr = args(0), argpat = args(1), argrep = args(2); + octave_value argstr = args(0); + octave_value argpat = args(1); + octave_value argrep = args(2); if (argpat.is_string () && argrep.is_string ()) { const Array pat = argpat.char_array_value (); diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/strfns.cc --- a/libinterp/corefcn/strfns.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/strfns.cc Tue Jan 07 16:07:54 2014 -0500 @@ -585,7 +585,7 @@ if (args.length () == 2) { - retval = do_strcmp_fun (args (0), args (1), 0, + retval = do_strcmp_fun (args(0), args(1), 0, "strcmp", strcmp_array_op, strcmp_str_op); } else @@ -647,7 +647,8 @@ strncmp_array_op (const charNDArray& s1, const charNDArray& s2, octave_idx_type n) { - octave_idx_type l1 = s1.numel (), l2 = s2.numel (); + octave_idx_type l1 = s1.numel (); + octave_idx_type l2 = s2.numel (); return (n > 0 && n <= l1 && n <= l2 && std::equal (s1.data (), s1.data () + n, s2.data ())); } @@ -658,7 +659,8 @@ static bool strncmp_str_op (const std::string& s1, const std::string& s2, octave_idx_type n) { - octave_idx_type l1 = s1.length (), l2 = s2.length (); + octave_idx_type l1 = s1.length (); + octave_idx_type l2 = s2.length (); return (n > 0 && n <= l1 && n <= l2 && std::equal (s1.data (), s1.data () + n, s2.data ())); } @@ -781,7 +783,7 @@ if (args.length () == 2) { - retval = do_strcmp_fun (args (0), args (1), 0, + retval = do_strcmp_fun (args(0), args(1), 0, "strcmpi", strcmpi_array_op, strcmpi_str_op); } else @@ -799,7 +801,8 @@ strncmpi_array_op (const charNDArray& s1, const charNDArray& s2, octave_idx_type n) { - octave_idx_type l1 = s1.numel (), l2 = s2.numel (); + octave_idx_type l1 = s1.numel (); + octave_idx_type l2 = s2.numel (); return (n > 0 && n <= l1 && n <= l2 && std::equal (s1.data (), s1.data () + n, s2.data (), icmp_char_eq ())); @@ -810,7 +813,8 @@ strncmpi_str_op (const std::string& s1, const std::string& s2, octave_idx_type n) { - octave_idx_type l1 = s1.length (), l2 = s2.length (); + octave_idx_type l1 = s1.length (); + octave_idx_type l2 = s2.length (); return (n > 0 && n <= l1 && n <= l2 && std::equal (s1.data (), s1.data () + n, s2.data (), icmp_char_eq ())); diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/symtab.cc --- a/libinterp/corefcn/symtab.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/symtab.cc Tue Jan 07 16:07:54 2014 -0500 @@ -38,6 +38,7 @@ #include "dirfns.h" #include "input.h" #include "load-path.h" +#include "ov-classdef.h" #include "ov-fcn.h" #include "ov-usr-fcn.h" #include "pager.h" @@ -383,11 +384,13 @@ std::string dir_name; - std::string file_name = load_path::find_method (name, name, dir_name); + std::string file_name = load_path::find_method (name, name, dir_name, + package_name); if (! file_name.empty ()) { - octave_function *fcn = load_fcn_from_file (file_name, dir_name, name); + octave_function *fcn = load_fcn_from_file (file_name, dir_name, name, + package_name); if (fcn) { @@ -396,6 +399,31 @@ class_constructors[name] = retval; } } + else + { + // Classdef constructors can be defined anywhere in the path, not + // necessarily in @-folders. Look for a normal function and load it. + // If the loaded function is a classdef constructor, store it as such + // and restore function_on_path to its previous value. + + octave_value old_function_on_path = function_on_path; + + octave_value maybe_cdef_ctor = find_user_function (); + + if (maybe_cdef_ctor.is_defined ()) + { + octave_function *fcn = maybe_cdef_ctor.function_value (true); + + if (fcn && fcn->is_classdef_constructor ()) + { + retval = maybe_cdef_ctor; + + class_constructors[name] = retval; + + function_on_path = old_function_on_path; + } + } + } return retval; } @@ -406,47 +434,57 @@ { octave_value retval; - if (name == dispatch_type) + if (full_name () == dispatch_type) retval = load_class_constructor (); else { - std::string dir_name; + octave_function *cm = cdef_manager::find_method_symbol (name, + dispatch_type); - std::string file_name = load_path::find_method (dispatch_type, name, - dir_name); + if (cm) + retval = octave_value (cm); - if (! file_name.empty ()) + if (! retval.is_defined ()) { - octave_function *fcn = load_fcn_from_file (file_name, dir_name, - dispatch_type); + std::string dir_name; - if (fcn) + std::string file_name = load_path::find_method (dispatch_type, name, + dir_name); + + if (! file_name.empty ()) { - retval = octave_value (fcn); + octave_function *fcn = load_fcn_from_file (file_name, dir_name, + dispatch_type); - class_methods[dispatch_type] = retval; - } - } + if (fcn) + { + retval = octave_value (fcn); - if (retval.is_undefined ()) - { - // Search parent classes + class_methods[dispatch_type] = retval; + } + } - const std::list& plist = parent_classes (dispatch_type); - - std::list::const_iterator it = plist.begin (); - - while (it != plist.end ()) + if (retval.is_undefined ()) { - retval = find_method (*it); + // Search parent classes - if (retval.is_defined ()) + const std::list& plist = + parent_classes (dispatch_type); + + std::list::const_iterator it = plist.begin (); + + while (it != plist.end ()) { - class_methods[dispatch_type] = retval; - break; + retval = find_method (*it); + + if (retval.is_defined ()) + { + class_methods[dispatch_type] = retval; + break; + } + + it++; } - - it++; } } } @@ -787,6 +825,13 @@ if (fcn.is_defined ()) return fcn; + // Package + + fcn = find_package (); + + if (fcn.is_defined ()) + return fcn; + // Built-in function (might be undefined). return built_in_function; @@ -975,7 +1020,7 @@ std::string dir_name = file_name.substr (0, pos); - octave_function *fcn = load_fcn_from_file (file_name, dir_name, + octave_function *fcn = load_fcn_from_file (file_name, dir_name, "", "", name, true); if (fcn) @@ -998,11 +1043,13 @@ { std::string dir_name; - std::string file_name = load_path::find_fcn (name, dir_name); + std::string file_name = load_path::find_fcn (name, dir_name, + package_name); if (! file_name.empty ()) { - octave_function *fcn = load_fcn_from_file (file_name, dir_name); + octave_function *fcn = load_fcn_from_file (file_name, dir_name, "", + package_name); if (fcn) function_on_path = octave_value (fcn); @@ -1012,6 +1059,25 @@ return function_on_path; } +octave_value +symbol_table::fcn_info::fcn_info_rep::find_package (void) +{ + // FIXME: implement correct way to check out of date package + //if (package.is_defined ()) + // out_of_date_check (package); + + if (! (error_state || package.is_defined ())) + { + octave_function * fcn = + cdef_manager::find_package_symbol (full_name ()); + + if (fcn) + package = octave_value (fcn); + } + + return package; +} + // Insert INF_CLASS in the set of class names that are considered // inferior to SUP_CLASS. Return FALSE if INF_CLASS is currently // marked as superior to SUP_CLASS. @@ -1069,10 +1135,11 @@ symbol_table::fcn_info::fcn_info_rep::dump (std::ostream& os, const std::string& prefix) const { - os << prefix << name + os << prefix << full_name () << " [" << (cmdline_function.is_defined () ? "c" : "") << (built_in_function.is_defined () ? "b" : "") + << (package.is_defined () ? "p" : "") << "]\n"; std::string tprefix = prefix + " "; diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/symtab.h --- a/libinterp/corefcn/symtab.h Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/symtab.h Tue Jan 07 16:07:54 2014 -0500 @@ -756,10 +756,19 @@ public: fcn_info_rep (const std::string& nm) - : name (nm), subfunctions (), private_functions (), + : name (nm), package_name (), subfunctions (), private_functions (), class_constructors (), class_methods (), dispatch_map (), cmdline_function (), autoload_function (), function_on_path (), - built_in_function (), count (1) { } + built_in_function (), count (1) + { + size_t pos = name.rfind ('.'); + + if (pos != std::string::npos) + { + package_name = name.substr (0, pos); + name = name.substr (pos+1); + } + } octave_value load_private_function (const std::string& dir_name); @@ -775,6 +784,8 @@ octave_value find_autoload (void); + octave_value find_package (void); + octave_value find_user_function (void); bool is_user_function_defined (void) const @@ -883,6 +894,11 @@ clear_user_function (); } + void clear_package (void) + { + package = octave_value (); + } + void clear (bool force = false) { clear_map (subfunctions, force); @@ -892,6 +908,7 @@ clear_autoload_function (force); clear_user_function (force); + clear_package (); } void add_dispatch (const std::string& type, const std::string& fname) @@ -915,8 +932,18 @@ void dump (std::ostream& os, const std::string& prefix) const; + std::string full_name (void) const + { + if (package_name.empty ()) + return name; + else + return package_name + "." + name; + } + std::string name; + std::string package_name; + // Scope id to function object. std::map subfunctions; @@ -938,6 +965,8 @@ octave_value function_on_path; + octave_value package; + octave_value built_in_function; octave_refcount count; diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/syscalls.cc --- a/libinterp/corefcn/syscalls.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/syscalls.cc Tue Jan 07 16:07:54 2014 -0500 @@ -511,7 +511,7 @@ if (nargin == 3) { - octave_stream strm = octave_stream_list::lookup (args (0), "fcntl"); + octave_stream strm = octave_stream_list::lookup (args(0), "fcntl"); if (! error_state) { diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/toplev.cc --- a/libinterp/corefcn/toplev.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/toplev.cc Tue Jan 07 16:07:54 2014 -0500 @@ -1251,8 +1251,6 @@ { false, "CAMD_LIBS", OCTAVE_CONF_CAMD_LIBS }, { false, "CARBON_LIBS", OCTAVE_CONF_CARBON_LIBS }, { false, "CC", OCTAVE_CONF_CC }, - // FIXME: CC_VERSION is deprecated. Remove in version 3.12 - { false, "CC_VERSION", OCTAVE_CONF_CC_VERSION }, { false, "CCOLAMD_CPPFLAGS", OCTAVE_CONF_CCOLAMD_CPPFLAGS }, { false, "CCOLAMD_LDFLAGS", OCTAVE_CONF_CCOLAMD_LDFLAGS }, { false, "CCOLAMD_LIBS", OCTAVE_CONF_CCOLAMD_LIBS }, @@ -1275,8 +1273,6 @@ { false, "CXXCPP", OCTAVE_CONF_CXXCPP }, { false, "CXXFLAGS", OCTAVE_CONF_CXXFLAGS }, { false, "CXXPICFLAG", OCTAVE_CONF_CXXPICFLAG }, - // FIXME: CXX_VERSION is deprecated. Remove in version 3.12 - { false, "CXX_VERSION", OCTAVE_CONF_CXX_VERSION }, { false, "DEFAULT_PAGER", OCTAVE_DEFAULT_PAGER }, { false, "DEFS", OCTAVE_CONF_DEFS }, { false, "DL_LD", OCTAVE_CONF_DL_LD }, diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/tril.cc --- a/libinterp/corefcn/tril.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/tril.cc Tue Jan 07 16:07:54 2014 -0500 @@ -42,7 +42,8 @@ static Array do_tril (const Array& a, octave_idx_type k, bool pack) { - octave_idx_type nr = a.rows (), nc = a.columns (); + octave_idx_type nr = a.rows (); + octave_idx_type nc = a.columns (); const T *avec = a.fortran_vec (); octave_idx_type zero = 0; @@ -83,7 +84,8 @@ static Array do_triu (const Array& a, octave_idx_type k, bool pack) { - octave_idx_type nr = a.rows (), nc = a.columns (); + octave_idx_type nr = a.rows (); + octave_idx_type nc = a.columns (); const T *avec = a.fortran_vec (); octave_idx_type zero = 0; @@ -211,7 +213,7 @@ print_usage (); else { - octave_value arg = args (0); + octave_value arg = args(0); dim_vector dims = arg.dims (); if (dims.length () != 2) @@ -274,7 +276,8 @@ if (arg.numel () == 0) return arg; - octave_idx_type nr = dims(0), nc = dims (1); + octave_idx_type nr = dims(0); + octave_idx_type nc = dims(1); // The sole purpose of the below is to force the correct // matrix size. This would not be necessary if the diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/txt-eng-ft.cc --- a/libinterp/corefcn/txt-eng-ft.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/txt-eng-ft.cc Tue Jan 07 16:07:54 2014 -0500 @@ -635,7 +635,8 @@ FT_UInt glyph_index, previous = 0; std::string str = e.string_value (); - size_t n = str.length (), curr = 0; + size_t n = str.length (); + size_t curr = 0; mbstate_t ps; memset (&ps, 0, sizeof (ps)); // Initialize state to 0. wchar_t wc; diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/utils.cc --- a/libinterp/corefcn/utils.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/utils.cc Tue Jan 07 16:07:54 2014 -0500 @@ -303,7 +303,7 @@ If the second optional argument @qcode{\"all\"} is supplied, return\n\ a cell array containing the list of all files that have the same\n\ name in the path. If no files are found, return an empty cell array.\n\ -@seealso{file_in_path, find_dir_in_path, path}\n\ +@seealso{file_in_path, dir_in_loadpath, path}\n\ @end deftypefn") { octave_value retval; @@ -380,7 +380,7 @@ If the third optional argument @qcode{\"all\"} is supplied, return\n\ a cell array containing the list of all files that have the same\n\ name in the path. If no files are found, return an empty cell array.\n\ -@seealso{file_in_loadpath, find_dir_in_path, path}\n\ +@seealso{file_in_loadpath, dir_in_loadpath, path}\n\ @end deftypefn") { octave_value retval; @@ -892,10 +892,10 @@ %!error make_absolute_filename ("foo", "bar") */ -DEFUN (find_dir_in_path, args, , +DEFUN (dir_in_loadpath, args, , "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} find_dir_in_path (@var{dir})\n\ -@deftypefnx {Built-in Function} {} find_dir_in_path (@var{dir}, \"all\")\n\ +@deftypefn {Built-in Function} {} dir_in_loadpath (@var{dir})\n\ +@deftypefnx {Built-in Function} {} dir_in_loadpath (@var{dir}, \"all\")\n\ Return the full name of the path element matching @var{dir}. The\n\ match is performed at the end of each path element. For example, if\n\ @var{dir} is @qcode{\"foo/bar\"}, it matches the path element\n\ @@ -926,7 +926,7 @@ retval = Cell (load_path::find_matching_dirs (dir)); } else - error ("find_dir_in_path: DIR must be a directory name"); + error ("dir_in_loadpath: DIR must be a directory name"); } else print_usage (); @@ -937,8 +937,8 @@ /* ## FIXME: We need system-dependent tests here. -%!error find_dir_in_path () -%!error find_dir_in_path ("foo", "bar", 1) +%!error dir_in_loadpath () +%!error dir_in_loadpath ("foo", "bar", 1) */ DEFUNX ("errno", Ferrno, args, , diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/variables.cc --- a/libinterp/corefcn/variables.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/variables.cc Tue Jan 07 16:07:54 2014 -0500 @@ -548,7 +548,7 @@ Check only for directories.\n\ @end table\n\ \n\ -@seealso{file_in_loadpath, file_in_path, find_dir_in_path, stat}\n\ +@seealso{file_in_loadpath, file_in_path, dir_in_loadpath, stat}\n\ @end deftypefn") { octave_value retval = false; @@ -1405,7 +1405,9 @@ param.modifier = 'r'; param.parameter_length = 0; - int a = 0, b = -1, balance = 1; + int a = 0; + int b = -1; + int balance = 1; unsigned int items; size_t pos; std::string cmd; diff -r e42d4f152766 -r 8f256148d82b libinterp/corefcn/xdiv.cc --- a/libinterp/corefcn/xdiv.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/corefcn/xdiv.cc Tue Jan 07 16:07:54 2014 -0500 @@ -713,7 +713,9 @@ if (! mx_div_conform (a, d)) return MT (); - octave_idx_type m = a.rows (), n = d.rows (), l = d.length (); + octave_idx_type m = a.rows (); + octave_idx_type n = d.rows (); + octave_idx_type l = d.length (); MT x (m, n); typedef typename DMT::element_type S; typedef typename MT::element_type T; @@ -794,7 +796,10 @@ if (! mx_leftdiv_conform (d, a, blas_no_trans)) return MT (); - octave_idx_type m = d.cols (), n = a.cols (), k = a.rows (), l = d.length (); + octave_idx_type m = d.cols (); + octave_idx_type n = a.cols (); + octave_idx_type k = a.rows (); + octave_idx_type l = d.length (); MT x (m, n); typedef typename DMT::element_type S; typedef typename MT::element_type T; @@ -871,8 +876,11 @@ if (! mx_div_conform (a, d)) return MT (); - octave_idx_type m = a.rows (), n = d.rows (), k = d.cols (); - octave_idx_type l = std::min (m, n), lk = std::min (l, k); + octave_idx_type m = a.rows (); + octave_idx_type n = d.rows (); + octave_idx_type k = d.cols (); + octave_idx_type l = std::min (m, n); + octave_idx_type lk = std::min (l, k); MT x (m, n); typedef typename DMT::element_type S; typedef typename MT::element_type T; @@ -943,8 +951,11 @@ if (! mx_leftdiv_conform (d, a, blas_no_trans)) return MT (); - octave_idx_type m = d.cols (), n = a.cols (), k = d.rows (); - octave_idx_type l = std::min (m, n), lk = std::min (l, k); + octave_idx_type m = d.cols (); + octave_idx_type n = a.cols (); + octave_idx_type k = d.rows (); + octave_idx_type l = std::min (m, n); + octave_idx_type lk = std::min (l, k); MT x (m, n); typedef typename DMT::element_type S; typedef typename MT::element_type T; diff -r e42d4f152766 -r 8f256148d82b libinterp/dldfcn/__delaunayn__.cc --- a/libinterp/dldfcn/__delaunayn__.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/dldfcn/__delaunayn__.cc Tue Jan 07 16:07:54 2014 -0500 @@ -175,7 +175,8 @@ facetT *facet; vertexT *vertex, **vertexp; - octave_idx_type nf = 0, i = 0; + octave_idx_type nf = 0; + octave_idx_type i = 0; FORALLfacets { diff -r e42d4f152766 -r 8f256148d82b libinterp/dldfcn/qr.cc --- a/libinterp/dldfcn/qr.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/dldfcn/qr.cc Tue Jan 07 16:07:54 2014 -0500 @@ -744,7 +744,9 @@ bool check_qr_dims (const octave_value& q, const octave_value& r, bool allow_ecf = false) { - octave_idx_type m = q.rows (), k = r.rows (), n = r.columns (); + octave_idx_type m = q.rows (); + octave_idx_type k = r.rows (); + octave_idx_type n = r.columns (); return ((q.ndims () == 2 && r.ndims () == 2 && k == q.columns ()) && (m == k || (allow_ecf && k == n && k < m))); } diff -r e42d4f152766 -r 8f256148d82b libinterp/dldfcn/symrcm.cc --- a/libinterp/dldfcn/symrcm.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/dldfcn/symrcm.cc Tue Jan 07 16:07:54 2014 -0500 @@ -487,7 +487,8 @@ octave_idx_type s = 0; // head- and tail-indices for the queue - octave_idx_type qt = 0, qh = 0; + octave_idx_type qt = 0; + octave_idx_type qh = 0; CMK_Node v, w; // dimension of the matrix octave_idx_type N = nr; diff -r e42d4f152766 -r 8f256148d82b libinterp/dldfcn/tsearch.cc --- a/libinterp/dldfcn/tsearch.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/dldfcn/tsearch.cc Tue Jan 07 16:07:54 2014 -0500 @@ -110,8 +110,10 @@ const octave_idx_type np = xi.length (); ColumnVector values (np); - double x0 = 0.0, y0 = 0.0; - double a11 = 0.0, a12 = 0.0, a21 = 0.0, a22 = 0.0, det = 0.0; + double x0, y0, a11, a12, a21, a22, det; + x0 = y0 = 0.0; + a11 = a12 = a21 = a22 = 0.0; + det = 0.0; octave_idx_type k = nelem; // k is a counter of elements for (octave_idx_type kp = 0; kp < np; kp++) diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/module.mk --- a/libinterp/octave-value/module.mk Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/module.mk Tue Jan 07 16:07:54 2014 -0500 @@ -36,6 +36,7 @@ octave-value/ov-cell.h \ octave-value/ov-ch-mat.h \ octave-value/ov-class.h \ + octave-value/ov-classdef.h \ octave-value/ov-colon.h \ octave-value/ov-complex.h \ octave-value/ov-cs-list.h \ @@ -94,6 +95,7 @@ octave-value/ov-cell.cc \ octave-value/ov-ch-mat.cc \ octave-value/ov-class.cc \ + octave-value/ov-classdef.cc \ octave-value/ov-colon.cc \ octave-value/ov-complex.cc \ octave-value/ov-cs-list.cc \ diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-base-diag.cc --- a/libinterp/octave-value/ov-base-diag.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-base-diag.cc Tue Jan 07 16:07:54 2014 -0500 @@ -441,7 +441,8 @@ bool octave_base_diag::load_ascii (std::istream& is) { - octave_idx_type r = 0, c = 0; + octave_idx_type r = 0; + octave_idx_type c = 0; bool success = true; if (extract_keyword (is, "rows", r, true) diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-base-int.cc --- a/libinterp/octave-value/ov-base-int.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-base-int.cc Tue Jan 07 16:07:54 2014 -0500 @@ -347,7 +347,8 @@ return (empty > 0); int rank = dv.length (); - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid, data_hid; + space_hid = data_hid = -1; OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank); // Octave uses column-major, while HDF5 uses row-major ordering @@ -550,7 +551,8 @@ hid_t save_type_hid = HDF5_SAVE_TYPE; bool retval = true; hsize_t dimens[3]; - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid, data_hid; + space_hid = data_hid = -1; space_hid = H5Screate_simple (0, dimens, 0); if (space_hid < 0) return false; diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-base-mat.cc --- a/libinterp/octave-value/ov-base-mat.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-base-mat.cc Tue Jan 07 16:07:54 2014 -0500 @@ -351,7 +351,8 @@ { // optimize all scalar indices. Don't construct an index array, // but rather calc a scalar index directly. - octave_idx_type k = 1, j = 0; + octave_idx_type k = 1; + octave_idx_type j = 0; for (octave_idx_type i = 0; i < n_idx; i++) { j += idx_vec(i)(0) * k; diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-base-sparse.cc --- a/libinterp/octave-value/ov-base-sparse.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-base-sparse.cc Tue Jan 07 16:07:54 2014 -0500 @@ -440,27 +440,55 @@ octave_value octave_base_sparse::map (octave_base_value::unary_mapper_t umap) const { + if (umap == umap_xtolower || umap == umap_xtoupper) + return matrix; + // Try the map on the dense value. + // FIXME: We should probably be smarter about this, especially for the + // cases that are expected to return sparse matrices. octave_value retval = this->full_value ().map (umap); // Sparsify the result if possible. - // FIXME: intentionally skip this step for string mappers. Is this wanted? - if (umap >= umap_xisalnum && umap <= umap_xtoupper) - return retval; - switch (retval.builtin_type ()) + switch (umap) { - case btyp_double: - retval = retval.sparse_matrix_value (); + case umap_xisalnum: + case umap_xisalpha: + case umap_xisascii: + case umap_xiscntrl: + case umap_xisdigit: + case umap_xisgraph: + case umap_xislower: + case umap_xisprint: + case umap_xispunct: + case umap_xisspace: + case umap_xisupper: + case umap_xisxdigit: + case umap_xtoascii: + // FIXME: intentionally skip this step for string mappers. + // Is this wanted? break; - case btyp_complex: - retval = retval.sparse_complex_matrix_value (); - break; - case btyp_bool: - retval = retval.sparse_bool_matrix_value (); - break; + default: - break; + { + switch (retval.builtin_type ()) + { + case btyp_double: + retval = retval.sparse_matrix_value (); + break; + + case btyp_complex: + retval = retval.sparse_complex_matrix_value (); + break; + + case btyp_bool: + retval = retval.sparse_bool_matrix_value (); + break; + + default: + break; + } + } } return retval; diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-bool-mat.cc --- a/libinterp/octave-value/ov-bool-mat.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-bool-mat.cc Tue Jan 07 16:07:54 2014 -0500 @@ -421,7 +421,8 @@ return (empty > 0); int rank = dv.length (); - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid, data_hid; + space_hid = data_hid = -1; bool retval = true; boolNDArray m = bool_array_value (); diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-bool-sparse.cc --- a/libinterp/octave-value/ov-bool-sparse.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-bool-sparse.cc Tue Jan 07 16:07:54 2014 -0500 @@ -358,7 +358,8 @@ if (group_hid < 0) return false; - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid, data_hid; + space_hid = data_hid = -1; bool retval = true; SparseBoolMatrix m = sparse_bool_matrix_value (); octave_idx_type tmp; diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-bool.cc --- a/libinterp/octave-value/ov-bool.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-bool.cc Tue Jan 07 16:07:54 2014 -0500 @@ -165,7 +165,8 @@ bool /* save_as_floats */) { hsize_t dimens[3]; - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid, data_hid; + space_hid = data_hid = -1; bool retval = true; space_hid = H5Screate_simple (0, dimens, 0); diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-cell.cc --- a/libinterp/octave-value/ov-cell.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-cell.cc Tue Jan 07 16:07:54 2014 -0500 @@ -1077,7 +1077,8 @@ return (empty > 0); hsize_t rank = dv.length (); - hid_t space_hid = -1, data_hid = -1, size_hid = -1; + hid_t space_hid, data_hid, size_hid; + space_hid = data_hid = size_hid = -1; #if HAVE_HDF5_18 data_hid = H5Gcreate (loc_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-class.cc --- a/libinterp/octave-value/ov-class.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-class.cc Tue Jan 07 16:07:54 2014 -0500 @@ -1279,7 +1279,8 @@ bool octave_class::reconstruct_parents (void) { - bool retval = true, might_have_inheritance = false; + bool retval = true; + bool might_have_inheritance = false; std::string dbgstr = "dork"; // First, check to see if there might be an issue with inheritance. diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-classdef.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/octave-value/ov-classdef.cc Tue Jan 07 16:07:54 2014 -0500 @@ -0,0 +1,3608 @@ +/* + +Copyright (C) 2012-2013 Michael Goffioul + +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 +. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "defun.h" +#include "load-path.h" +#include "ov-builtin.h" +#include "ov-classdef.h" +#include "ov-fcn-handle.h" +#include "ov-typeinfo.h" +#include "pt-assign.h" +#include "pt-classdef.h" +#include "pt-funcall.h" +#include "pt-misc.h" +#include "pt-stmt.h" +#include "pt-walk.h" +#include "singleton-cleanup.h" +#include "symtab.h" +#include "toplev.h" + +#include "Array.cc" + +static void +gripe_method_access (const std::string& from, const cdef_method& meth) +{ + octave_value acc = meth.get ("Access"); + std::string acc_s; + + if (acc.is_string ()) + acc_s = acc.string_value (); + else + acc_s = "class-restricted"; + + error ("%s: method `%s' has %s access and cannot be run in this context", + from.c_str (), meth.get_name ().c_str (), acc_s.c_str ()); +} + +static void +gripe_property_access (const std::string& from, const cdef_property& prop, + bool is_set = false) +{ + octave_value acc = prop.get (is_set ? "SetAccess" : "GetAccess"); + std::string acc_s; + + if (acc.is_string ()) + acc_s = acc.string_value (); + else + acc_s = "class-restricted"; + + if (is_set) + error ("%s: property `%s' has %s access and cannot be set in this context", + from.c_str (), prop.get_name ().c_str (), acc_s.c_str ()); + else + error ("%s: property `%s' has %s access and cannot be obtained in this context", + from.c_str (), prop.get_name ().c_str (), acc_s.c_str ()); +} + +static std::string +get_base_name (const std::string& nm) +{ + std::string::size_type pos = nm.find_last_of ('.'); + + if (pos != std::string::npos) + return nm.substr (pos + 1); + + return nm; +} + +static void +make_function_of_class (const std::string& class_name, + const octave_value& fcn) +{ + octave_function *of = fcn.function_value (); + + if (! error_state) + { + of->stash_dispatch_class (class_name); + + octave_user_function *uf = of->user_function_value (true); + + if (! error_state && uf) + { + if (get_base_name (class_name) == uf->name ()) + { + uf->mark_as_class_constructor (); + uf->mark_as_classdef_constructor (); + } + else + uf->mark_as_class_method (); + } + } +} + +static void +make_function_of_class (const cdef_class& cls, const octave_value& fcn) +{ + make_function_of_class (cls.get_name (), fcn); +} + +static octave_value +make_fcn_handle (octave_builtin::fcn ff, const std::string& nm) +{ + octave_value fcn (new octave_builtin (ff, nm)); + + octave_value fcn_handle (new octave_fcn_handle (fcn, nm)); + + return fcn_handle; +} + +static octave_value +make_fcn_handle (const octave_value& fcn, const std::string& nm) +{ + octave_value retval; + + if (fcn.is_defined ()) + retval = octave_value (new octave_fcn_handle (fcn, nm)); + + return retval; +} + +inline octave_value_list +execute_ov (octave_value val, const octave_value_list& args, int nargout) +{ + std::list idx (1, args); + + std::string type ("("); + + return val.subsref (type, idx, nargout); +} + +static cdef_class +lookup_class (const std::string& name, bool error_if_not_found = true, + bool load_if_not_found = true) +{ + return cdef_manager::find_class (name, error_if_not_found, + load_if_not_found); +} + +static cdef_class +lookup_class (const cdef_class& cls) +{ + // FIXME: placeholder for the time being, the purpose + // is to centralized any class update activity here. + + return cls; +} + +static cdef_class +lookup_class (const octave_value& ov) +{ + if (ov.is_string()) + return lookup_class (ov.string_value ()); + else + { + cdef_class cls (to_cdef (ov)); + + if (! error_state) + return lookup_class (cls); + } + + return cdef_class (); +} + +static std::list +lookup_classes (const Cell& cls_list) +{ + std::list retval; + + for (int i = 0; i < cls_list.numel (); i++) + { + cdef_class c = lookup_class (cls_list(i)); + + if (! error_state) + retval.push_back (c); + else + { + retval.clear (); + break; + } + } + + return retval; +} + +static octave_value +to_ov (const std::list& class_list) +{ + Cell cls (class_list.size (), 1); + int i = 0; + + for (std::list::const_iterator it = class_list.begin (); + it != class_list.end (); ++it, ++i) + cls(i) = to_ov (*it); + + return octave_value (cls); +} + +static bool +is_superclass (const cdef_class& clsa, const cdef_class& clsb, + bool allow_equal = true, int max_depth = -1) +{ + bool retval = false; + + if (allow_equal && clsa == clsb) + retval = true; + else if (max_depth != 0) + { + Cell c = clsb.get ("SuperClasses").cell_value (); + + for (int i = 0; ! error_state && ! retval && i < c.numel (); i++) + { + cdef_class cls = lookup_class (c(i)); + + if (! error_state) + retval = is_superclass (clsa, cls, true, + max_depth < 0 ? max_depth : max_depth-1); + } + } + + return retval; +} + +inline bool +is_strict_superclass (const cdef_class& clsa, const cdef_class& clsb) +{ return is_superclass (clsa, clsb, false); } + +inline bool +is_direct_superclass (const cdef_class& clsa, const cdef_class& clsb) +{ return is_superclass (clsa, clsb, false, 1); } + +static octave_value_list +class_get_properties (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval; + + if (args.length () == 1 && args(0).type_name () == "object") + { + cdef_class cls (to_cdef (args(0))); + + retval(0) = cls.get_properties (); + } + + return retval; +} + +static cdef_class +get_class_context (std::string& name, bool& in_constructor) +{ + cdef_class cls; + + octave_function* fcn = octave_call_stack::current (); + + in_constructor = false; + + if (fcn && + (fcn->is_class_method () + || fcn->is_classdef_constructor () + || fcn->is_anonymous_function_of_class () + || (fcn->is_private_function () + && ! fcn->dispatch_class ().empty ()))) + { + cls = lookup_class (fcn->dispatch_class ()); + if (! error_state) + { + name = fcn->name (); + in_constructor = fcn->is_classdef_constructor (); + } + } + + return cls; +} + +inline cdef_class +get_class_context (void) +{ + std::string dummy_string; + bool dummy_bool; + + return get_class_context (dummy_string, dummy_bool); +} + +static bool +check_access (const cdef_class& cls, const octave_value& acc) +{ + if (acc.is_string ()) + { + std::string acc_s = acc.string_value (); + + if (acc_s == "public") + return true; + + cdef_class ctx = get_class_context (); + + // The access is private or protected, this requires a + // valid class context. + + if (! error_state && ctx.ok ()) + { + if (acc_s == "private") + return (ctx == cls); + else if (acc_s == "protected") + return is_superclass (cls, ctx); + else + panic_impossible (); + } + } + else if (acc.is_cell ()) + { + Cell acc_c = acc.cell_value (); + + cdef_class ctx = get_class_context (); + + // At this point, a class context is always required. + + if (! error_state && ctx.ok ()) + { + if (ctx == cls) + return true; + + for (int i = 0; ! error_state && i < acc.numel (); i++) + { + cdef_class acc_cls (to_cdef (acc_c(i))); + + if (! error_state) + { + if (is_superclass (acc_cls, ctx)) + return true; + } + } + } + } + else + error ("invalid property/method access in class `%s'", + cls.get_name ().c_str ()); + + return false; +} + +bool +is_method_executing (const octave_value& ov, const cdef_object& obj) +{ + octave_function* stack_fcn = octave_call_stack::current (); + + octave_function* method_fcn = ov.function_value (true); + + // Does the top of the call stack match our target function? + + if (stack_fcn && stack_fcn == method_fcn) + { + octave_user_function* uf = method_fcn->user_function_value (true); + + // We can only check the context object for user-function (not builtin), + // where we have access to the parameters (arguments and return values). + // That's ok as there's no need to call this function for builtin + // methods. + + if (uf) + { + // At this point, the method is executing, but we still need to + // check the context object for which the method is executing. For + // methods, it's the first argument of the function; for ctors, it + // is the first return value. + + tree_parameter_list* pl = uf->is_classdef_constructor () + ? uf->return_list () : uf->parameter_list (); + + if (pl && pl->size () > 0) + { + octave_value arg0 = pl->front ()->lvalue ().value (); + + if (arg0.is_defined () && arg0.type_name () == "object") + { + cdef_object arg0_obj = to_cdef (arg0); + + return obj.is (arg0_obj); + } + } + } + } + + return false; +} + +static octave_value_list +class_get_methods (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval; + + if (args.length () == 1 && args(0).type_name () == "object") + { + cdef_class cls (to_cdef (args(0))); + + retval(0) = cls.get_methods (); + } + + return retval; +} + +static octave_value_list +class_get_superclasses (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval; + + if (args.length () == 1 && args(0).type_name () == "object" + && args(0).class_name () == "meta.class") + { + cdef_class cls (to_cdef (args(0))); + + Cell classes = cls.get ("SuperClasses").cell_value (); + + retval(0) = to_ov (lookup_classes (classes)); + } + + return retval; +} + +static octave_value_list +class_get_inferiorclasses (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval; + + if (args.length () == 1 && args(0).type_name () == "object" + && args(0).class_name () == "meta.class") + { + cdef_class cls (to_cdef (args(0))); + + Cell classes = cls.get ("InferiorClasses").cell_value (); + + retval(0) = to_ov (lookup_classes (classes)); + } + + return retval; +} + +static octave_value_list +class_fromName (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval; + + if (args.length () == 1) + { + std::string name = args(0).string_value (); + + if (! error_state) + retval(0) = to_ov (lookup_class (name)); + else + error ("fromName: invalid class name, expected a string value"); + } + else + error ("fromName: invalid number of parameters"); + + return retval; +} + +static octave_value_list +class_fevalStatic (const octave_value_list& args, int nargout) +{ + octave_value_list retval; + + if (args.length () > 1 && args(0).type_name () == "object") + { + cdef_class cls (to_cdef (args(0))); + + if (! error_state) + { + std::string meth_name = args(1).string_value (); + + if (! error_state) + { + cdef_method meth = cls.find_method (meth_name); + + if (meth.ok ()) + { + if (meth.is_static ()) + retval = meth.execute (args.splice (0, 2), nargout, + true, "fevalStatic"); + else + error ("fevalStatic: method `%s' is not static", + meth_name.c_str ()); + } + else + error ("fevalStatic: method not found: %s", + meth_name.c_str ()); + } + else + error ("fevalStatic: invalid method name, expected a string value"); + } + error ("fevalStatic: invalid object, expected a meta.class object"); + } + else + error ("fevalStatic: invalid arguments"); + + return retval; +} + +static octave_value_list +class_getConstant (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval; + + if (args.length () == 2 && args(0).type_name () == "object" + && args(0).class_name () == "meta.class") + { + cdef_class cls = to_cdef (args(0)); + + if (! error_state) + { + std::string prop_name = args(1).string_value (); + + if (! error_state) + { + cdef_property prop = cls.find_property (prop_name); + + if (prop.ok ()) + { + if (prop.is_constant ()) + retval(0) = prop.get_value (true, "getConstant"); + else + error ("getConstant: property `%s' is not constant", + prop_name.c_str ()); + } + else + error ("getConstant: property not found: %s", + prop_name.c_str ()); + } + else + error ("getConstant: invalid property name, expected a string value"); + } + else + error ("getConstant: invalid object, expected a meta.class object"); + } + else + error ("getConstant: invalid arguments"); + + return retval; +} + +#define META_CLASS_CMP(OP, CLSA, CLSB, FUN) \ +static octave_value_list \ +class_ ## OP (const octave_value_list& args, int /* nargout */) \ +{ \ + octave_value_list retval; \ +\ + if (args.length () == 2 \ + && args(0).type_name () == "object" && args(1).type_name () == "object" \ + && args(0).class_name () == "meta.class" && args(1).class_name () == "meta.class") \ + { \ + cdef_class clsa = to_cdef (args(0)); \ +\ + cdef_class clsb = to_cdef (args(1)); \ +\ + if (! error_state) \ + retval(0) = FUN (CLSA, CLSB); \ + else \ + error (#OP ": invalid objects, expected meta.class objects"); \ + } \ + else \ + error (#OP ": invalid arguments"); \ +\ + return retval; \ +} + +META_CLASS_CMP (lt, clsb, clsa, is_strict_superclass) +META_CLASS_CMP (le, clsb, clsa, is_superclass) +META_CLASS_CMP (gt, clsa, clsb, is_strict_superclass) +META_CLASS_CMP (ge, clsa, clsb, is_superclass) +META_CLASS_CMP (eq, clsa, clsb, operator==) +META_CLASS_CMP (ne, clsa, clsb, operator!=) + +octave_value_list +property_get_defaultvalue (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval; + + if (args.length () == 1 && args(0).type_name () == "object") + { + cdef_property prop (to_cdef (args(0))); + + retval(0) = prop.get ("DefaultValue"); + + if (! retval(0).is_defined ()) + error_with_id ("Octave:class:NotDefaultDefined", + "no default value for property `%s'", + prop.get_name ().c_str ()); + } + + return retval; +} + +static octave_value_list +handle_delete (const octave_value_list& /* args */, int /* nargout */) +{ + octave_value_list retval; + + // FIXME: implement this + + return retval; +} + +static cdef_class +make_class (const std::string& name, + const std::list& super_list = std::list ()) +{ + cdef_class cls (name, super_list); + + cls.set_class (cdef_class::meta_class ()); + cls.put ("Abstract", false); + cls.put ("ConstructOnLoad", false); + cls.put ("ContainingPackage", Matrix ()); + cls.put ("Description", std::string ()); + cls.put ("DetailedDescription", std::string ()); + cls.put ("Events", Cell ()); + cls.put ("Hidden", false); + cls.put ("InferiorClasses", Cell ()); + cls.put ("Methods", Cell ()); + cls.put ("Properties", Cell ()); + cls.put ("Sealed", false); + + if (name == "handle") + { + cls.put ("HandleCompatible", true); + cls.mark_as_handle_class (); + } + else if (super_list.empty ()) + { + cls.put ("HandleCompatible", false); + } + else + { + bool all_handle_compatible = true; + bool has_handle_class = false; + + for (std::list::const_iterator it = super_list.begin (); + it != super_list.end (); ++it) + { + all_handle_compatible = all_handle_compatible && it->get ("HandleCompatible").bool_value (); + has_handle_class = has_handle_class || it->is_handle_class (); + } + + if (has_handle_class && ! all_handle_compatible) + ::error ("%s: cannot mix handle and non-HandleCompatible classes", + name.c_str ()); + else + { + cls.put ("HandleCompatible", all_handle_compatible); + if (has_handle_class) + cls.mark_as_handle_class (); + } + } + + if (error_state) + return cdef_class (); + + if (! name.empty ()) + cdef_manager::register_class (cls); + + return cls; +} + +static cdef_class +make_class (const std::string& name, const cdef_class& super) +{ + return make_class (name, std::list (1, super)); +} + +static cdef_class +make_meta_class (const std::string& name, const cdef_class& super) +{ + cdef_class cls = make_class (name, super); + + cls.put ("Sealed", true); + cls.mark_as_meta_class (); + + return cls; +} + +static cdef_property +make_property (const cdef_class& cls, const std::string& name, + const octave_value& get_method = Matrix (), + const std::string& get_access = "public", + const octave_value& set_method = Matrix (), + const std::string& set_access = "public") +{ + cdef_property prop (name); + + prop.set_class (cdef_class::meta_property ()); + prop.put ("Description", std::string ()); + prop.put ("DetailedDescription", std::string ()); + prop.put ("Abstract", false); + prop.put ("Constant", false); + prop.put ("GetAccess", get_access); + prop.put ("SetAccess", set_access); + prop.put ("Dependent", false); + prop.put ("Transient", false); + prop.put ("Hidden", false); + prop.put ("GetObservable", false); + prop.put ("SetObservable", false); + prop.put ("GetMethod", get_method); + prop.put ("SetMethod", set_method); + prop.put ("DefiningClass", to_ov (cls)); + prop.put ("DefaultValue", octave_value ()); + prop.put ("HasDefault", false); + + std::string class_name = cls.get_name (); + + if (! get_method.is_empty ()) + make_function_of_class (class_name, get_method); + if (! set_method.is_empty ()) + make_function_of_class (class_name, set_method); + + return prop; +} + +inline cdef_property +make_attribute (const cdef_class& cls, const std::string& name) +{ + return make_property (cls, name, Matrix (), "public", Matrix (), "private"); +} + +static cdef_method +make_method (const cdef_class& cls, const std::string& name, + const octave_value& fcn,const std::string& m_access = "public", + bool is_static = false) +{ + cdef_method meth (name); + + meth.set_class (cdef_class::meta_method ()); + meth.put ("Abstract", false); + meth.put ("Access", m_access); + meth.put ("DefiningClass", to_ov (cls)); + meth.put ("Description", std::string ()); + meth.put ("DetailedDescription", std::string ()); + meth.put ("Hidden", false); + meth.put ("Sealed", true); + meth.put ("Static", is_static); + + if (fcn.is_defined ()) + make_function_of_class (cls, fcn); + + meth.set_function (fcn); + + return meth; +} + +inline cdef_method +make_method (const cdef_class& cls, const std::string& name, + octave_builtin::fcn ff, const std::string& m_access = "public", + bool is_static = false) +{ + octave_value fcn (new octave_builtin (ff, name)); + + return make_method (cls, name, fcn, m_access, is_static); +} + +static cdef_package +make_package (const std::string& nm, + const std::string& parent = std::string ()) +{ + cdef_package pack (nm); + + pack.set_class (cdef_class::meta_package ()); + if (parent.empty ()) + pack.put ("ContainingPackage", Matrix ()); + else + pack.put ("ContainingPackage", to_ov (cdef_manager::find_package (parent))); + + if (! nm.empty ()) + cdef_manager::register_package (pack); + + return pack; +} + +//---------------------------------------------------------------------------- + +DEFINE_OCTAVE_ALLOCATOR (octave_classdef); + +int octave_classdef::t_id (-1); + +const std::string octave_classdef::t_name ("object"); + +void +octave_classdef::register_type (void) +{ + t_id = octave_value_typeinfo::register_type + (octave_classdef::t_name, "", octave_value (new octave_classdef ())); +} + +octave_value_list +octave_classdef::subsref (const std::string& type, + const std::list& idx, + int nargout) +{ + size_t skip = 0; + octave_value_list retval; + + // FIXME: should check "subsref" method first + + retval = object.subsref (type, idx, nargout, skip, cdef_class ()); + + if (! error_state) + { + if (type.length () > skip && idx.size () > skip) + retval = retval(0).next_subsref (nargout, type, idx, skip); + } + + return retval; +} + +octave_value +octave_classdef::subsref (const std::string& type, + const std::list& idx, + bool auto_add) +{ + size_t skip = 0; + octave_value_list retval; + + // FIXME: should check "subsref" method first + // ? not sure this still applied with auto_add version of subsref + + retval = object.subsref (type, idx, 1, skip, cdef_class (), auto_add); + + if (! error_state) + { + if (type.length () > skip && idx.size () > skip) + retval = retval(0).next_subsref (1, type, idx, skip); + } + + return retval.length () > 0 ? retval(0) : octave_value (); +} + +octave_value +octave_classdef::subsasgn (const std::string& type, + const std::list& idx, + const octave_value& rhs) +{ + // FIXME: should check "subsasgn" method first + + return object.subsasgn (type, idx, rhs); +} + +octave_value +octave_classdef::undef_subsasgn (const std::string& type, + const std::list& idx, + const octave_value& rhs) +{ + if (type.length () == 1 && type[0] == '(') + { + object = object.make_array (); + + if (! error_state) + return subsasgn (type, idx, rhs); + } + else + return octave_base_value::undef_subsasgn (type, idx, rhs); + + return octave_value (); +} + +//---------------------------------------------------------------------------- + +class octave_classdef_meta : public octave_function +{ +public: + octave_classdef_meta (const cdef_meta_object& obj) + : object (obj) { } + + ~octave_classdef_meta (void) + { object.meta_release (); } + + octave_function* function_value (bool = false) { return this; } + + octave_value_list + subsref (const std::string& type, + const std::list& idx, + int nargout) + { return object.meta_subsref (type, idx, nargout); } + + octave_value + subsref (const std::string& type, + const std::list& idx) + { + octave_value_list retval; + + retval = subsref (type, idx, 1); + + return (retval.length () > 0 ? retval(0) : octave_value ()); + } + + octave_value_list + do_multi_index_op (int nargout, const octave_value_list& idx) + { + // Emulate ()-type meta subsref + + std::list l (1, idx); + std::string type ("("); + + return subsref (type, l, nargout); + } + + bool is_postfix_index_handled (char type) const + { return object.meta_is_postfix_index_handled (type); } + +private: + cdef_meta_object object; +}; + +//---------------------------------------------------------------------------- + +class octave_classdef_superclass_ref : public octave_function +{ +public: + octave_classdef_superclass_ref (const octave_value_list& a) + : octave_function (), args (a) { } + + ~octave_classdef_superclass_ref (void) { } + + octave_value_list + subsref (const std::string& type, + const std::list& idx, + int nargout) + { + size_t skip = 0; + octave_value_list retval; + + switch (type[0]) + { + case '(': + skip = 1; + retval = do_multi_index_op (type.length () > 1 ? 1 : nargout, + idx.front ()); + break; + default: + retval = do_multi_index_op (1, octave_value_list ()); + break; + } + + if (! error_state) + { + if (type.length () > skip && idx.size () > skip + && retval.length () > 0) + retval = retval(0).next_subsref (nargout, type, idx, skip); + } + + return retval; + } + + octave_value + subsref (const std::string& type, + const std::list& idx) + { + octave_value_list retval; + + retval = subsref (type, idx, 1); + + return (retval.length () > 0 ? retval(0) : octave_value ()); + } + + octave_value_list + do_multi_index_op (int nargout, const octave_value_list& idx) + { + octave_value_list retval; + + std::string meth_name; + bool in_constructor; + cdef_class ctx; + + ctx = get_class_context (meth_name, in_constructor); + + if (! error_state && ctx.ok ()) + { + std::string mname = args(0).string_value (); + std::string pname = args(1).string_value (); + std::string cname = args(2).string_value (); + + std::string cls_name = (pname.empty () ? + cname : pname + "." + cname); + cdef_class cls = lookup_class (cls_name); + + if (! error_state) + { + if (in_constructor) + { + if (is_direct_superclass (cls, ctx)) + { + if (is_constructed_object (mname)) + { + octave_value& sym = symbol_table::varref (mname); + + cls.run_constructor (to_cdef_ref (sym), idx); + + retval(0) = sym; + } + else + ::error ("cannot call superclass constructor with " + "variable `%s'", mname.c_str ()); + } + else + ::error ("`%s' is not a direct superclass of `%s'", + cls_name.c_str (), ctx.get_name ().c_str ()); + } + else + { + if (mname == meth_name) + { + if (is_strict_superclass (cls, ctx)) + { + // I see 2 possible implementations here: + // 1) use cdef_object::subsref with a different class + // context; this avoids duplicating code, but + // assumes the object is always the first argument + // 2) lookup the method manually and call + // cdef_method::execute; this duplicates part of + // logic in cdef_object::subsref, but avoid the + // assumption of 1) + // Not being sure about the assumption of 1), I + // go with option 2) for the time being. + + cdef_method meth = cls.find_method (meth_name, false); + + if (meth.ok ()) + retval = meth.execute (idx, nargout, true, + meth_name); + else + ::error ("no method `%s' found in superclass `%s'", + meth_name.c_str (), cls_name.c_str ()); + } + else + ::error ("`%s' is not a superclass of `%s'", + cls_name.c_str (), ctx.get_name ().c_str ()); + } + else + ::error ("method name mismatch (`%s' != `%s')", + mname.c_str (), meth_name.c_str ()); + } + } + } + else if (! error_state) + ::error ("superclass calls can only occur in methods or constructors"); + + return retval; + } + +private: + bool is_constructed_object (const std::string nm) + { + octave_function *of = octave_call_stack::current (); + + if (of->is_classdef_constructor ()) + { + octave_user_function *uf = of->user_function_value (true); + + if (uf) + { + tree_parameter_list *ret_list = uf->return_list (); + + if (ret_list && ret_list->length () == 1) + return (ret_list->front ()->name () == nm); + } + } + + return false; + } + +private: + octave_value_list args; +}; + +//---------------------------------------------------------------------------- + +string_vector +cdef_object_rep::map_keys (void) const +{ + cdef_class cls = get_class (); + + if (cls.ok ()) + return cls.get_names (); + + return string_vector (); +} + +octave_value_list +cdef_object_scalar::subsref (const std::string& type, + const std::list& idx, + int nargout, size_t& skip, + const cdef_class& context, bool auto_add) +{ + skip = 0; + + cdef_class cls = (context.ok () ? context : get_class ()); + + octave_value_list retval; + + if (! cls.ok ()) + return retval; + + switch (type[0]) + { + case '.': + { + std::string name = (idx.front ())(0).string_value (); + + cdef_method meth = cls.find_method (name); + + if (meth.ok ()) + { + int _nargout = (type.length () > 2 ? 1 : nargout); + + octave_value_list args; + + skip = 1; + + if (type.length () > 1 && type[1] == '(') + { + std::list::const_iterator it = idx.begin (); + + args = *++it; + + skip++; + } + + if (meth.is_static ()) + retval = meth.execute (args, _nargout, true, "subsref"); + else + { + refcount++; + retval = meth.execute (cdef_object (this), args, _nargout, + true, "subsref"); + } + } + + if (skip == 0 && ! error_state) + { + cdef_property prop = cls.find_property (name); + + if (prop.ok ()) + { + if (prop.is_constant ()) + retval(0) = prop.get_value (true, "subsref"); + else + { + refcount++; + retval(0) = prop.get_value (cdef_object (this), + true, "subsref"); + } + + skip = 1; + } + else + error ("subsref: unknown method or property: %s", name.c_str ()); + } + break; + } + + case '(': + { + refcount++; + + cdef_object this_obj (this); + + Array arr (dim_vector (1, 1), this_obj); + + cdef_object new_obj = cdef_object (new cdef_object_array (arr)); + + new_obj.set_class (get_class ()); + + retval = new_obj.subsref (type, idx, nargout, skip, cls, auto_add); + } + break; + + default: + error ("object cannot be indexed with `%c'", type[0]); + break; + } + + return retval; +} + +octave_value +cdef_object_scalar::subsasgn (const std::string& type, + const std::list& idx, + const octave_value& rhs) +{ + octave_value retval; + + cdef_class cls = get_class (); + + switch (type[0]) + { + case '.': + { + std::string name = (idx.front ())(0).string_value (); + + if (! error_state) + { + cdef_property prop = cls.find_property (name); + + if (prop.ok ()) + { + if (prop.is_constant ()) + error ("subsasgn: cannot assign constant property: %s", + name.c_str ()); + else + { + refcount++; + + cdef_object obj (this); + + if (type.length () == 1) + { + prop.set_value (obj, rhs, true, "subsasgn"); + + if (! error_state) + retval = to_ov (obj); + } + else + { + octave_value val = + prop.get_value (obj, true, "subsasgn"); + + if (! error_state) + { + std::list args (idx); + + args.erase (args.begin ()); + + val = val.assign (octave_value::op_asn_eq, + type.substr (1), args, rhs); + + if (! error_state) + { + if (val.class_name () != "object" + || ! to_cdef (val).is_handle_object ()) + prop.set_value (obj, val, true, "subsasgn"); + + if (! error_state) + retval = to_ov (obj); + } + } + } + } + } + else + error ("subsasgn: unknown property: %s", name.c_str ()); + } + } + break; + + case '(': + { + refcount++; + + cdef_object this_obj (this); + + Array arr (dim_vector (1, 1), this_obj); + + cdef_object new_obj = cdef_object (new cdef_object_array (arr)); + + new_obj.set_class (get_class ()); + + octave_value tmp = new_obj.subsasgn (type, idx, rhs); + + if (! error_state) + retval = tmp; + } + break; + + default: + error ("subsasgn: object cannot be index with `%c'", type[0]); + break; + } + + return retval; +} + +void +cdef_object_scalar::mark_for_construction (const cdef_class& cls) +{ + std::string cls_name = cls.get_name (); + + Cell supcls = cls.get ("SuperClasses").cell_value (); + + if (! error_state) + { + std::list supcls_list = lookup_classes (supcls); + + if (! error_state) + ctor_list[cls] = supcls_list; + } +} + +octave_value_list +cdef_object_array::subsref (const std::string& type, + const std::list& idx, + int /* nargout */, size_t& skip, + const cdef_class& /* context */, bool auto_add) +{ + octave_value_list retval; + + skip = 1; + + switch (type[0]) + { + case '(': + { + const octave_value_list& ival = idx.front (); + bool is_scalar = true; + Array iv (dim_vector (1, ival.length ())); + + for (int i = 0; ! error_state && i < ival.length (); i++) + { + iv(i) = ival(i).index_vector (); + if (! error_state) + is_scalar = is_scalar && iv(i).is_scalar (); + } + + if (! error_state) + { + Array ires = array.index (iv, auto_add); + + if (! error_state) + { + // If resizing is enabled (auto_add = true), it's possible + // indexing was out-of-bound and the result array contains + // invalid cdef_objects. + + if (auto_add) + fill_empty_values (ires); + + if (is_scalar) + retval(0) = to_ov (ires(0)); + else + { + cdef_object array_obj (new cdef_object_array (ires)); + + array_obj.set_class (get_class ()); + + retval(0) = to_ov (array_obj); + } + } + } + } + break; + + case '.': + if (type.size () == 1 && idx.size () == 1) + { + Cell c (dims ()); + + octave_idx_type n = array.numel (); + + // dummy variables + size_t dummy_skip; + cdef_class dummy_cls; + + for (octave_idx_type i = 0; i < n; i++) + { + octave_value_list r = array(i).subsref (type, idx, 1, dummy_skip, + dummy_cls); + + if (! error_state) + { + if (r.length () > 0) + c(i) = r(0); + } + else + break; + } + + if (! error_state) + retval(0) = octave_value (c, true); + + break; + } + // fall through "default" + + default: + ::error ("can't perform indexing operation on array of %s objects", + class_name ().c_str ()); + break; + } + + return retval; +} + +octave_value +cdef_object_array::subsasgn (const std::string& type, + const std::list& idx, + const octave_value& rhs) +{ + octave_value retval; + + switch (type[0]) + { + case '(': + if (type.length () == 1) + { + cdef_object rhs_obj = to_cdef (rhs); + + if (! error_state) + { + if (rhs_obj.get_class () == get_class ()) + { + const octave_value_list& ival = idx.front (); + bool is_scalar = true; + Array iv (dim_vector (1, ival.length ())); + + for (int i = 0; ! error_state && i < ival.length (); i++) + { + iv(i) = ival(i).index_vector (); + if (! error_state) + is_scalar = is_scalar && iv(i).is_scalar (); + } + + if (! error_state) + { + Array rhs_mat; + + if (! rhs_obj.is_array ()) + { + rhs_mat = Array (dim_vector (1, 1)); + rhs_mat(0) = rhs_obj; + } + else + rhs_mat = rhs_obj.array_value (); + + if (! error_state) + { + octave_idx_type n = array.numel (); + + array.assign (iv, rhs_mat, cdef_object ()); + + if (! error_state) + { + if (array.numel () > n) + fill_empty_values (); + + if (! error_state) + { + refcount++; + retval = to_ov (cdef_object (this)); + } + } + } + } + } + else + ::error ("can't assign %s object into array of %s objects.", + rhs_obj.class_name ().c_str (), + class_name ().c_str ()); + } + } + else + { + const octave_value_list& ival = idx.front (); + + bool is_scalar = true; + + Array iv (dim_vector (1, ival.length ())); + + for (int i = 0; ! error_state && i < ival.length (); i++) + { + iv(i) = ival(i).index_vector (); + + if (! error_state) + { + is_scalar = is_scalar && iv(i).is_scalar (); + + if (! is_scalar) + error ("subsasgn: invalid indexing for object array " + "assignment, the index must reference a single " + "object in the array."); + } + } + + if (! error_state) + { + Array a = array.index (iv, true); + + if (a.numel () != 1) + error ("subsasgn: invalid indexing for object array " + "assignment"); + + if (! error_state) + { + cdef_object obj = a(0); + + int ignore_copies = 0; + + // If the object in 'a' is not valid, this means the index + // was out-of-bound and we need to create a new object. + + if (! obj.ok ()) + obj = get_class ().construct_object (octave_value_list ()); + else + // Optimize the subsasgn call to come. There are 2 copies + // that we can safely ignore: + // - 1 in "array" + // - 1 in "a" + ignore_copies = 2; + + std::list next_idx (idx); + + next_idx.erase (next_idx.begin ()); + + octave_value tmp = obj.subsasgn (type.substr (1), next_idx, + rhs, ignore_copies); + + if (! error_state) + { + cdef_object robj = to_cdef (tmp); + + if (robj.ok () + && ! robj.is_array () + && robj.get_class () == get_class ()) + { + // Small optimization, when dealing with handle + // objects, we don't need to re-assign the result + // of subsasgn back into the array. + + if (! robj.is (a(0))) + { + Array rhs_a (dim_vector (1, 1), + robj); + + octave_idx_type n = array.numel (); + + array.assign (iv, rhs_a); + + if (array.numel () > n) + fill_empty_values (); + } + + refcount++; + + retval = to_ov (cdef_object (this)); + } + else + error ("subasgn: invalid assignment into array of %s " + "objects", class_name ().c_str ()); + } + } + } + } + break; + + default: + ::error ("can't perform indexing operation on array of %s objects", + class_name ().c_str ()); + break; + } + + return retval; +} + +void +cdef_object_array::fill_empty_values (Array& arr) +{ + cdef_class cls = get_class (); + + if (! error_state) + { + cdef_object obj; + + int n = arr.numel (); + + for (int i = 0; ! error_state && i < n; i++) + { + if (! arr.xelem (i).ok ()) + { + if (! obj.ok ()) + { + obj = cls.construct_object (octave_value_list ()); + + if (! error_state) + arr.xelem (i) = obj; + } + else + arr.xelem (i) = obj.copy (); + } + } + } +} + +bool cdef_object_scalar::is_constructed_for (const cdef_class& cls) const +{ + return (is_constructed () + || ctor_list.find (cls) == ctor_list.end ()); +} + +bool cdef_object_scalar::is_partially_constructed_for (const cdef_class& cls) const +{ + std::map< cdef_class, std::list >::const_iterator it; + + if (is_constructed ()) + return true; + else if ((it = ctor_list.find (cls)) == ctor_list.end () + || it->second.empty ()) + return true; + + for (std::list::const_iterator lit = it->second.begin (); + lit != it->second.end (); ++lit) + if (! is_constructed_for (*lit)) + return false; + + return true; +} + +handle_cdef_object::~handle_cdef_object (void) +{ + gnulib::printf ("deleting %s object (handle)\n", + get_class ().get_name ().c_str ()); +} + +value_cdef_object::~value_cdef_object (void) +{ + gnulib::printf ("deleting %s object (value)\n", + get_class ().get_name ().c_str ()); +} + +cdef_class::cdef_class_rep::cdef_class_rep (const std::list& superclasses) + : cdef_meta_object_rep (), member_count (0), handle_class (false), + object_count (0), meta (false) +{ + put ("SuperClasses", to_ov (superclasses)); + implicit_ctor_list = superclasses; +} + +cdef_method +cdef_class::cdef_class_rep::find_method (const std::string& nm, bool local) +{ + method_iterator it = method_map.find (nm); + + if (it == method_map.end ()) + { + // FIXME: look into class directory + } + else + { + cdef_method& meth = it->second; + + // FIXME: check if method reload needed + + if (meth.ok ()) + return meth; + } + + if (! local) + { + // Look into superclasses + + Cell super_classes = get ("SuperClasses").cell_value (); + + for (int i = 0; i < super_classes.numel (); i++) + { + cdef_class cls = lookup_class (super_classes(i)); + + if (! error_state) + { + cdef_method meth = cls.find_method (nm); + + if (meth.ok ()) + return meth; + } + } + } + + return cdef_method (); +} + +class ctor_analyzer : public tree_walker +{ +public: + ctor_analyzer (const std::string& ctor, const std::string& obj) + : tree_walker (), who (ctor), obj_name (obj) { } + + void visit_statement_list (tree_statement_list& t) + { + for (tree_statement_list::const_iterator it = t.begin (); + ! error_state && it != t.end (); ++it) + (*it)->accept (*this); + } + + void visit_statement (tree_statement& t) + { + if (t.is_expression ()) + t.expression ()->accept (*this); + } + + void visit_simple_assignment (tree_simple_assignment& t) + { + t.right_hand_side ()->accept (*this); + } + + void visit_multi_assignment (tree_multi_assignment& t) + { + t.right_hand_side ()->accept (*this); + } + + void visit_index_expression (tree_index_expression& t) + { + t.expression ()->accept (*this); + } + + void visit_funcall (tree_funcall& t) + { + octave_value fcn = t.function (); + + if (fcn.is_function ()) + { + octave_function *of = fcn.function_value (true); + + if (of) + { + if (of->name () == "__superclass_reference__") + { + octave_value_list args = t.arguments (); + + if (args(0).string_value () == obj_name) + { + std::string package_name = args(1).string_value (); + std::string class_name = args(2).string_value (); + + std::string ctor_name = (package_name.empty () + ? class_name + : package_name + "." + class_name); + + cdef_class cls = lookup_class (ctor_name, false); + + if (cls.ok ()) + ctor_list.push_back (cls); + } + } + } + } + } + + std::list get_constructor_list (void) const + { return ctor_list; } + + // NO-OP + void visit_anon_fcn_handle (tree_anon_fcn_handle&) { } + void visit_argument_list (tree_argument_list&) { } + void visit_binary_expression (tree_binary_expression&) { } + void visit_break_command (tree_break_command&) { } + void visit_colon_expression (tree_colon_expression&) { } + void visit_continue_command (tree_continue_command&) { } + void visit_global_command (tree_global_command&) { } + void visit_persistent_command (tree_persistent_command&) { } + void visit_decl_elt (tree_decl_elt&) { } + void visit_decl_init_list (tree_decl_init_list&) { } + void visit_simple_for_command (tree_simple_for_command&) { } + void visit_complex_for_command (tree_complex_for_command&) { } + void visit_octave_user_script (octave_user_script&) { } + void visit_octave_user_function (octave_user_function&) { } + void visit_function_def (tree_function_def&) { } + void visit_identifier (tree_identifier&) { } + void visit_if_clause (tree_if_clause&) { } + void visit_if_command (tree_if_command&) { } + void visit_if_command_list (tree_if_command_list&) { } + void visit_switch_case (tree_switch_case&) { } + void visit_switch_case_list (tree_switch_case_list&) { } + void visit_switch_command (tree_switch_command&) { } + void visit_matrix (tree_matrix&) { } + void visit_cell (tree_cell&) { } + void visit_no_op_command (tree_no_op_command&) { } + void visit_constant (tree_constant&) { } + void visit_fcn_handle (tree_fcn_handle&) { } + void visit_parameter_list (tree_parameter_list&) { } + void visit_postfix_expression (tree_postfix_expression&) { } + void visit_prefix_expression (tree_prefix_expression&) { } + void visit_return_command (tree_return_command&) { } + void visit_return_list (tree_return_list&) { } + void visit_try_catch_command (tree_try_catch_command&) { } + void visit_unwind_protect_command (tree_unwind_protect_command&) { } + void visit_while_command (tree_while_command&) { } + void visit_do_until_command (tree_do_until_command&) { } + +private: + /* The name of the constructor being analyzed */ + std::string who; + + /* The name of the first output argument of the constructor */ + std::string obj_name; + + /* The list of superclass constructors that are explicitly called */ + std::list ctor_list; +}; + +void +cdef_class::cdef_class_rep::install_method (const cdef_method& meth) +{ + method_map[meth.get_name ()] = meth; + + member_count++; + + if (meth.is_constructor ()) + { + // Analyze the constructor code to determine what superclass + // constructors are called explicitly. + + octave_function *of = meth.get_function ().function_value (true); + + if (of) + { + octave_user_function *uf = of->user_function_value (true); + + if (uf) + { + tree_parameter_list *ret_list = uf->return_list (); + tree_statement_list *body = uf->body (); + + if (ret_list && ret_list->size () == 1) + { + std::string obj_name = ret_list->front ()->name (); + ctor_analyzer a (meth.get_name (), obj_name); + + body->accept (a); + if (! error_state) + { + std::list explicit_ctor_list + = a.get_constructor_list (); + + for (std::list::const_iterator it = explicit_ctor_list.begin (); + ! error_state && it != explicit_ctor_list.end (); ++it) + { + gnulib::printf ("explicit superclass constructor: %s\n", + it->get_name ().c_str ()); + implicit_ctor_list.remove (*it); + } + } + } + else + ::error ("%s: invalid constructor output arguments", + meth.get_name ().c_str ()); + } + } + } +} + +void +cdef_class::cdef_class_rep::load_all_methods (void) +{ + // FIXME: re-scan class directory +} + +Cell +cdef_class::cdef_class_rep::get_methods (void) +{ + std::map meths; + + find_methods (meths, false); + + if (! error_state) + { + Cell c (meths.size (), 1); + + int idx = 0; + + for (std::map::const_iterator it = meths.begin (); + it != meths.end (); ++it, ++idx) + c (idx, 0) = to_ov (it->second); + + return c; + } + + return Cell (); +} + +void +cdef_class::cdef_class_rep::find_methods (std::map& meths, + bool only_inherited) +{ + load_all_methods (); + + method_const_iterator it; + + for (it = method_map.begin (); it != method_map.end (); ++it) + { + if (! it->second.is_constructor ()) + { + std::string nm = it->second.get_name (); + + if (meths.find (nm) == meths.end ()) + { + if (only_inherited) + { + octave_value acc = it->second.get ("Access"); + + if (! acc.is_string () + || acc.string_value () == "private") + continue; + } + + meths[nm] = it->second; + } + } + } + + // Look into superclasses + + Cell super_classes = get ("SuperClasses").cell_value (); + + for (int i = 0; i < super_classes.numel (); i++) + { + cdef_class cls = lookup_class (super_classes(i)); + + if (! error_state) + cls.get_rep ()->find_methods (meths, true); + else + break; + } +} + +cdef_property +cdef_class::cdef_class_rep::find_property (const std::string& nm) +{ + property_iterator it = property_map.find (nm); + + if (it != property_map.end ()) + { + cdef_property& prop = it->second; + + if (prop.ok ()) + return prop; + } + + // Look into superclasses + + Cell super_classes = get ("SuperClasses").cell_value (); + + for (int i = 0; i < super_classes.numel (); i++) + { + cdef_class cls = lookup_class (super_classes(i)); + + if (! error_state) + { + cdef_property prop = cls.find_property (nm); + + if (prop.ok ()) + return prop; + } + } + + return cdef_property (); +} + +void +cdef_class::cdef_class_rep::install_property (const cdef_property& prop) +{ + property_map[prop.get_name ()] = prop; + + member_count++; +} + +Cell +cdef_class::cdef_class_rep::get_properties (void) +{ + std::map props; + + find_properties (props, false); + + if (! error_state) + { + Cell c (props.size (), 1); + + int idx = 0; + + for (std::map::const_iterator it = props.begin (); + it != props.end (); ++it, ++idx) + c (idx, 0) = to_ov (it->second); + + return c; + } + + return Cell (); +} + +void +cdef_class::cdef_class_rep::find_properties (std::map& props, + bool only_inherited) +{ + property_const_iterator it; + + for (it = property_map.begin (); ! error_state && it != property_map.end (); + ++it) + { + std::string nm = it->second.get_name (); + + if (props.find (nm) == props.end ()) + { + if (only_inherited) + { + octave_value acc = it->second.get ("GetAccess"); + + if (! acc.is_string () + || acc.string_value () == "private") + continue; + } + + props[nm] = it->second; + } + } + + // Look into superclasses + + Cell super_classes = get ("SuperClasses").cell_value (); + + for (int i = 0; ! error_state && i < super_classes.numel (); i++) + { + cdef_class cls = lookup_class (super_classes(i)); + + if (! error_state) + cls.get_rep ()->find_properties (props, true); + else + break; + } +} + +void +cdef_class::cdef_class_rep::find_names (std::set& names, + bool all) +{ + load_all_methods (); + + for (method_const_iterator it = method_map.begin (); + ! error_state && it != method_map.end(); ++it) + { + if (! it->second.is_constructor ()) + { + std::string nm = it->second.get_name (); + + if (! all) + { + octave_value acc = it->second.get ("Access"); + + if (! acc.is_string() + || acc.string_value () != "public") + continue; + } + + names.insert (nm); + } + } + + for (property_const_iterator it = property_map.begin (); + ! error_state && it != property_map.end (); ++it) + { + std::string nm = it->second.get_name (); + + if (! all) + { + octave_value acc = it->second.get ("GetAccess"); + + if (! acc.is_string() + || acc.string_value () != "public") + continue; + } + + names.insert (nm); + } + + // Look into superclasses + + Cell super_classes = get ("SuperClasses").cell_value (); + + for (int i = 0; ! error_state && i < super_classes.numel (); i++) + { + cdef_class cls = lookup_class (super_classes(i)); + + if (! error_state) + cls.get_rep ()->find_names (names, all); + else + break; + } +} + +string_vector +cdef_class::cdef_class_rep::get_names (void) +{ + std::set names; + + find_names (names, false); + + if (! error_state) + { + string_vector v (names.size ()); + + int idx = 0; + for (std::set::const_iterator it = names.begin (); + it != names.end (); ++it, ++idx) + v[idx] = *it; + + return v.sort (true); + } + + return string_vector (); +} + +void +cdef_class::cdef_class_rep::delete_object (cdef_object obj) +{ + method_iterator it = method_map.find ("delete"); + + if (it != method_map.end ()) + { + cdef_class cls = obj.get_class (); + + obj.set_class (wrap ()); + + it->second.execute (obj, octave_value_list (), 0, false); + + obj.set_class (cls); + } + + // FIXME: should we destroy corresponding properties here? + + // Call "delete" in super classes + + Cell super_classes = get ("SuperClasses").cell_value (); + + for (int i = 0; i < super_classes.numel (); i++) + { + cdef_class cls = lookup_class (super_classes(i)); + + if (!error_state) + cls.delete_object (obj); + } +} + +octave_value_list +cdef_class::cdef_class_rep::meta_subsref (const std::string& type, + const std::list& idx, + int nargout) +{ + size_t skip = 1; + + octave_value_list retval; + + switch (type[0]) + { + case '(': + // Constructor call + gnulib::printf ("constructor\n"); + retval(0) = construct (idx.front ()); + break; + + case '.': + // Static method, constant (or property?) + gnulib::printf ("static method/property\n"); + if (idx.front ().length () == 1) + { + std::string nm = idx.front ()(0).string_value (); + + if (! error_state) + { + cdef_method meth = find_method (nm); + + if (meth.ok ()) + { + if (meth.is_static ()) + { + octave_value_list args; + + if (type.length () > 1 && idx.size () > 1 + && type[1] == '(') + { + args = *(++(idx.begin ())); + skip++; + } + + retval = meth.execute (args, (type.length () > skip + ? 1 : nargout), true, + "meta.class"); + } + else + ::error ("method `%s' is not static", nm.c_str ()); + } + else + { + cdef_property prop = find_property (nm); + + if (prop.ok ()) + { + if (prop.is_constant ()) + retval(0) = prop.get_value (true, "meta.class"); + else + ::error ("property `%s' is not constant", + nm.c_str ()); + } + else + ::error ("no such method or property `%s'", nm.c_str ()); + } + } + else + ::error ("invalid meta.class indexing, expected a method or property name"); + } + else + ::error ("invalid meta.class indexing"); + break; + + default: + ::error ("invalid meta.class indexing"); + break; + } + + if (! error_state) + { + if (type.length () > skip && idx.size () > skip && ! retval.empty ()) + retval = retval(0).next_subsref (nargout, type, idx, skip); + } + + return retval; +} + +void +cdef_class::cdef_class_rep::meta_release (void) +{ + cdef_manager::unregister_class (wrap ()); +} + +void +cdef_class::cdef_class_rep::initialize_object (cdef_object& obj) +{ + // Populate the object with default property values + + std::list super_classes = lookup_classes (get ("SuperClasses").cell_value ()); + + if (! error_state) + { + for (std::list::iterator it = super_classes.begin (); + ! error_state && it != super_classes.end (); ++it) + it->initialize_object (obj); + + if (! error_state) + { + for (property_const_iterator it = property_map.begin (); + ! error_state && it != property_map.end (); ++it) + { + if (! it->second.get ("Dependent").bool_value ()) + { + octave_value pvalue = it->second.get ("DefaultValue"); + + if (pvalue.is_defined ()) + obj.put (it->first, pvalue); + else + obj.put (it->first, octave_value (Matrix ())); + } + } + + if (! error_state) + { + refcount++; + obj.mark_for_construction (cdef_class (this)); + } + } + } +} + +void +cdef_class::cdef_class_rep::run_constructor (cdef_object& obj, + const octave_value_list& args) +{ + octave_value_list empty_args; + + for (std::list::const_iterator it = implicit_ctor_list.begin (); + ! error_state && it != implicit_ctor_list.end (); ++it) + { + cdef_class supcls = lookup_class (*it); + + if (! error_state) + supcls.run_constructor (obj, empty_args); + } + + if (error_state) + return; + + std::string cls_name = get_name (); + std::string ctor_name = get_base_name (cls_name); + + cdef_method ctor = find_method (ctor_name); + + if (ctor.ok ()) + { + octave_value_list ctor_args (args); + octave_value_list ctor_retval; + + ctor_args.prepend (to_ov (obj)); + ctor_retval = ctor.execute (ctor_args, 1, true, "constructor"); + + if (! error_state) + { + if (ctor_retval.length () == 1) + obj = to_cdef (ctor_retval(0)); + else + { + ::error ("%s: invalid number of output arguments for classdef constructor", + ctor_name.c_str ()); + return; + } + } + } + + obj.mark_as_constructed (wrap ()); +} + +octave_value +cdef_class::cdef_class_rep::construct (const octave_value_list& args) +{ + cdef_object obj = construct_object (args); + + if (! error_state && obj.ok ()) + return to_ov (obj); + + return octave_value (); +} + +cdef_object +cdef_class::cdef_class_rep::construct_object (const octave_value_list& args) +{ + if (! is_abstract ()) + { + cdef_object obj; + + if (is_meta_class ()) + { + // This code path is only used to create empty meta objects + // as filler for the empty values within a meta object array. + + cdef_class this_cls = wrap (); + + static cdef_object empty_class; + + if (this_cls == cdef_class::meta_class ()) + { + if (! empty_class.ok ()) + empty_class = make_class ("", std::list ()); + obj = empty_class; + } + else if (this_cls == cdef_class::meta_property ()) + { + static cdef_property empty_property; + + if (! empty_class.ok ()) + empty_class = make_class ("", std::list ()); + if (! empty_property.ok ()) + empty_property = make_property (empty_class, ""); + obj = empty_property; + } + else if (this_cls == cdef_class::meta_method ()) + { + static cdef_method empty_method; + + if (! empty_class.ok ()) + empty_class = make_class ("", std::list ()); + if (! empty_method.ok ()) + empty_method = make_method (empty_class, "", octave_value ()); + obj = empty_method; + } + else if (this_cls == cdef_class::meta_package ()) + { + static cdef_package empty_package; + + if (! empty_package.ok ()) + empty_package = make_package (""); + obj = empty_package; + } + else + panic_impossible (); + + return obj; + } + else + { + if (is_handle_class ()) + obj = cdef_object (new handle_cdef_object ()); + else + obj = cdef_object (new value_cdef_object ()); + obj.set_class (wrap ()); + + initialize_object (obj); + + if (! error_state) + { + run_constructor (obj, args); + + if (! error_state) + return obj; + } + } + } + else + error ("cannot instantiate object for abstract class `%s'", + get_name ().c_str ()); + + return cdef_object (); +} + +static octave_value +compute_attribute_value (tree_classdef_attribute* t) +{ + if (t->expression ()) + { + if (t->expression ()->is_identifier ()) + { + std::string s = t->expression ()->name (); + + if (s == "public") + return std::string ("public"); + else if (s == "protected") + return std::string ("protected"); + else if (s == "private") + return std::string ("private"); + } + + return t->expression ()->rvalue1 (); + } + else + return octave_value (true); +} + +template +static std::string +attribute_value_to_string (T* t, octave_value v) +{ + if (v.is_string ()) + return v.string_value (); + else if (t->expression ()) + return t->expression ()->original_text (); + else + return std::string ("true"); +} + +cdef_class +cdef_class::make_meta_class (tree_classdef* t) +{ + cdef_class retval; + std::string class_name, full_class_name; + + // Class creation + + class_name = full_class_name = t->ident ()->name (); + if (! t->package_name ().empty ()) + full_class_name = t->package_name () + "." + full_class_name; + gnulib::printf ("class: %s\n", full_class_name.c_str ()); + + std::list slist; + + if (t->superclass_list ()) + { + for (tree_classdef_superclass_list::iterator it = t->superclass_list ()->begin (); + ! error_state && it != t->superclass_list ()->end (); ++it) + { + std::string sclass_name = + ((*it)->package () ? (*it)->package ()->name () + "." : std::string ()) + + (*it)->ident ()->name (); + + gnulib::printf ("superclass: %s\n", sclass_name.c_str ()); + + cdef_class sclass = lookup_class (sclass_name); + + if (! error_state) + { + if (! sclass.get ("Sealed").bool_value ()) + slist.push_back (sclass); + else + { + ::error ("`%s' cannot inherit from `%s', because it is sealed", + full_class_name.c_str (), sclass_name.c_str ()); + return retval; + } + } + else + return retval; + + } + } + + retval = ::make_class (full_class_name, slist); + + if (error_state) + return cdef_class (); + + // Package owning this class + + if (! t->package_name ().empty ()) + { + cdef_package pack = cdef_manager::find_package (t->package_name ()); + + if (! error_state && pack.ok ()) + retval.put ("ContainingPackage", to_ov (pack)); + } + + // Class attributes + + if (t->attribute_list ()) + { + for (tree_classdef_attribute_list::iterator it = t->attribute_list ()->begin (); + it != t->attribute_list ()->end (); ++it) + { + std::string aname = (*it)->ident ()->name (); + octave_value avalue = compute_attribute_value (*it); + + gnulib::printf ("class attribute: %s = %s\n", aname.c_str (), + attribute_value_to_string (*it, avalue).c_str ()); + retval.put (aname, avalue); + } + } + + tree_classdef_body* b = t->body (); + + if (b) + { + // Keep track of the get/set accessor methods. They will be used + // later on when creating properties. + + std::map get_methods; + std::map set_methods; + + // Method blocks + + std::list mb_list = b->methods_list (); + + for (tree_classdef_body::methods_list_iterator it = mb_list.begin (); + it != mb_list.end (); ++it) + { + std::map amap; + gnulib::printf ("method block\n"); + + // Method attributes + + if ((*it)->attribute_list ()) + { + for (tree_classdef_attribute_list::iterator ait = (*it)->attribute_list ()->begin (); + ait != (*it)->attribute_list ()->end (); ++ait) + { + std::string aname = (*ait)->ident ()->name (); + octave_value avalue = compute_attribute_value (*ait); + + gnulib::printf ("method attribute: %s = %s\n", aname.c_str (), + attribute_value_to_string (*ait, avalue).c_str ()); + amap[aname] = avalue; + } + } + + // Methods + + if ((*it)->element_list ()) + { + for (tree_classdef_methods_list::iterator mit = (*it)->element_list ()->begin (); + mit != (*it)->element_list ()->end (); ++mit) + { + std::string mname = mit->function_value ()->name (); + std::string mprefix = mname.substr (0, 4); + + if (mprefix == "get.") + get_methods[mname.substr (4)] = + make_fcn_handle (*mit, full_class_name + ">" + mname); + else if (mprefix == "set.") + set_methods[mname.substr (4)] = + make_fcn_handle (*mit, full_class_name + ">" + mname); + else + { + cdef_method meth = make_method (retval, mname, *mit); + + gnulib::printf ("%s: %s\n", (mname == class_name ? "constructor" : "method"), + mname.c_str ()); + for (std::map::iterator ait = amap.begin (); + ait != amap.end (); ++ait) + meth.put (ait->first, ait->second); + + retval.install_method (meth); + } + } + } + } + + // Property blocks + + // FIXME: default property expression should be able to call static + // methods of the class being constructed. A restricted CLASSNAME + // symbol should be added to the scope before evaluating default + // value expressions. + + std::list pb_list = b->properties_list (); + + for (tree_classdef_body::properties_list_iterator it = pb_list.begin (); + it != pb_list.end (); ++it) + { + std::map amap; + gnulib::printf ("property block\n"); + + // Property attributes + + if ((*it)->attribute_list ()) + { + for (tree_classdef_attribute_list::iterator ait = (*it)->attribute_list ()->begin (); + ait != (*it)->attribute_list ()->end (); ++ait) + { + std::string aname = (*ait)->ident ()->name (); + octave_value avalue = compute_attribute_value (*ait); + + gnulib::printf ("property attribute: %s = %s\n", aname.c_str (), + attribute_value_to_string (*ait, avalue).c_str ()); + if (aname == "Access") + { + amap["GetAccess"] = avalue; + amap["SetAccess"] = avalue; + } + else + amap[aname] = avalue; + } + } + + // Properties + + if ((*it)->element_list ()) + { + for (tree_classdef_property_list::iterator pit = (*it)->element_list ()->begin (); + pit != (*it)->element_list ()->end (); ++pit) + { + std::string prop_name = (*pit)->ident ()->name (); + + cdef_property prop = ::make_property (retval, prop_name); + + gnulib::printf ("property: %s\n", (*pit)->ident ()->name ().c_str ()); + if ((*pit)->expression ()) + { + octave_value pvalue = (*pit)->expression ()->rvalue1 (); + + gnulib::printf ("property default: %s\n", + attribute_value_to_string (*pit, pvalue).c_str ()); + prop.put ("DefaultValue", pvalue); + } + + // Install property attributes. This is done before assigning the + // property accessors so we can do validationby using cdef_property + // methods. + + for (std::map::iterator ait = amap.begin (); + ait != amap.end (); ++ait) + prop.put (ait->first, ait->second); + + // Install property access methods, if any. Remove the accessor + // methods from the temporary storage map, so we can detect which + // ones are invalid and do not correspond to a defined property. + + std::map::iterator git = + get_methods.find (prop_name); + + if (git != get_methods.end ()) + { + prop.put ("GetMethod", git->second); + get_methods.erase (git); + } + + std::map::iterator sit = + set_methods.find (prop_name); + + if (sit != set_methods.end ()) + { + prop.put ("SetMethod", sit->second); + set_methods.erase (sit); + } + + retval.install_property (prop); + } + } + } + } + + return retval; +} + +octave_function* +cdef_class::get_method_function (const std::string& /* nm */) +{ + octave_classdef_meta* p = new octave_classdef_meta (*this); + + return p; +} + +octave_value +cdef_property::cdef_property_rep::get_value (const cdef_object& obj, + bool do_check_access, + const std::string& who) +{ + octave_value retval; + + if (do_check_access && ! check_get_access ()) + { + gripe_property_access (who, wrap (), false); + + return retval; + } + + if (! obj.is_constructed ()) + { + cdef_class cls (to_cdef (get ("DefiningClass"))); + + if (! obj.is_partially_constructed_for (cls)) + { + ::error ("cannot reference properties of class `%s' for non-constructed object", + cls.get_name ().c_str ()); + return retval; + } + } + + octave_value get_fcn = get ("GetMethod"); + + // FIXME: should check whether we're already in get accessor method + + if (get_fcn.is_empty () || is_method_executing (get_fcn, obj)) + retval = obj.get (get ("Name").string_value ()); + else + { + octave_value_list args; + + args(0) = to_ov (obj); + + args = execute_ov (get_fcn, args, 1); + + if (! error_state) + retval = args(0); + } + + return retval; +} + +octave_value +cdef_property::cdef_property_rep::get_value (bool do_check_access, + const std::string& who) +{ + if (do_check_access && ! check_get_access ()) + { + gripe_property_access (who, wrap (), false); + + return octave_value (); + } + + return get ("DefaultValue"); +} + +bool +cdef_property::cdef_property_rep::is_recursive_set (const cdef_object& /* obj */) const +{ + // FIXME: implement + return false; +} + +void +cdef_property::cdef_property_rep::set_value (cdef_object& obj, + const octave_value& val, + bool do_check_access, + const std::string& who) +{ + if (do_check_access && ! check_set_access ()) + { + gripe_property_access (who, wrap (), true); + + return; + } + + if (! obj.is_constructed ()) + { + cdef_class cls (to_cdef (get ("DefiningClass"))); + + if (! obj.is_partially_constructed_for (cls)) + { + ::error ("cannot reference properties of class `%s' for non-constructed object", + cls.get_name ().c_str ()); + return; + } + } + + octave_value set_fcn = get ("SetMethod"); + + if (set_fcn.is_empty () || is_method_executing (set_fcn, obj)) + obj.put (get ("Name").string_value (), val); + else + { + octave_value_list args; + + args(0) = to_ov (obj); + args(1) = val; + + args = execute_ov (set_fcn, args, 1); + + if (! error_state) + { + if (args.length() > 0) + { + cdef_object new_obj = to_cdef (args(0)); + + if (! error_state) + obj = new_obj; + } + } + } +} + +bool +cdef_property::cdef_property_rep::check_get_access (void) const +{ + cdef_class cls (to_cdef (get ("DefiningClass"))); + + if (! error_state) + return ::check_access (cls, get ("GetAccess")); + + return false; +} + +bool +cdef_property::cdef_property_rep::check_set_access (void) const +{ + cdef_class cls (to_cdef (get ("DefiningClass"))); + + if (! error_state) + return ::check_access (cls, get ("SetAccess")); + + return false; +} + +void +cdef_method::cdef_method_rep::check_method (void) +{ + // FIXME: check whether re-load is needed +} + +octave_value_list +cdef_method::cdef_method_rep::execute (const octave_value_list& args, + int nargout, bool do_check_access, + const std::string& who) +{ + octave_value_list retval; + + if (do_check_access && ! check_access ()) + { + gripe_method_access (who, wrap ()); + + return retval; + } + + if (! get ("Abstract").bool_value ()) + { + check_method (); + + if (function.is_defined ()) + { + retval = execute_ov (function, args, nargout); + } + } + else + error ("%s: cannot execute abstract method", + get ("Name").string_value ().c_str ()); + + return retval; +} + +octave_value_list +cdef_method::cdef_method_rep::execute (const cdef_object& obj, + const octave_value_list& args, + int nargout, bool do_check_access, + const std::string& who) +{ + octave_value_list retval; + + if (do_check_access && ! check_access ()) + { + gripe_method_access (who, wrap ()); + + return retval; + } + + if (! get ("Abstract").bool_value ()) + { + check_method (); + + octave_value_list new_args; + + if (function.is_defined ()) + { + new_args.resize (args.length () + 1); + + new_args(0) = to_ov (obj); + for (int i = 0; i < args.length (); i++) + new_args(i+1) = args(i); + + retval = execute_ov (function, new_args, nargout); + } + } + else + error ("%s: cannot execute abstract method", + get ("Name").string_value ().c_str ()); + + return retval; +} + +bool +cdef_method::cdef_method_rep::is_constructor (void) const +{ + if (function.is_function()) + return function.function_value ()->is_classdef_constructor (); + + return false; +} + +bool +cdef_method::cdef_method_rep::check_access (void) const +{ + cdef_class cls (to_cdef (get ("DefiningClass"))); + + if (! error_state) + return ::check_access (cls, get ("Access")); + + return false; +} + +octave_value_list +cdef_method::cdef_method_rep::meta_subsref + (const std::string& type, const std::list& idx, + int nargout) +{ + octave_value_list retval; + + switch (type[0]) + { + case '(': + retval = execute (idx.front (), type.length () > 1 ? 1 : nargout, true); + break; + + default: + error ("invalid meta.method indexing"); + break; + } + + if (! error_state) + { + if (type.length () > 1 && idx.size () > 1 && ! retval.empty ()) + retval = retval(0).next_subsref (nargout, type, idx, 1); + } + + return retval; +} + +static cdef_package +lookup_package (const std::string& name) +{ + return cdef_manager::find_package (name); +} + +static octave_value_list +package_fromName (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval; + + if (args.length () == 1) + { + std::string name = args(0).string_value (); + + if (! error_state) + retval(0) = to_ov (lookup_package (name)); + else + error ("fromName: invalid package name, expected a string value"); + } + else + error ("fromName: invalid number of parameters"); + + return retval; +} + +static octave_value_list +package_get_classes (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval (1, Matrix ()); + + if (args.length () == 1 && args(0).type_name () == "object" + && args(0).class_name () == "meta.package") + { + cdef_package pack (to_cdef (args(0))); + + retval(0) = pack.get_classes (); + } + + return retval; +} + +static octave_value_list +package_get_functions (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval (1, Matrix ()); + + if (args.length () == 0 && args(0).type_name () == "object" + && args(0).class_name () == "meta.package") + { + cdef_package pack (to_cdef (args(0))); + + retval(0) = pack.get_functions (); + } + + return retval; +} + +static octave_value_list +package_get_packages (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval (1, Matrix ()); + + if (args.length () == 0 && args(0).type_name () == "object" + && args(0).class_name () == "meta.package") + { + cdef_package pack (to_cdef (args(0))); + + retval(0) = pack.get_packages (); + } + + return retval; +} + +static octave_value_list +package_getAllPackages (const octave_value_list& /* args */, + int /* nargout */) +{ + std::map toplevel_packages; + + std::list names = load_path::get_all_package_names (); + + toplevel_packages["meta"] = cdef_manager::find_package ("meta", false, + false); + + for (std::list::const_iterator it = names.begin (); + it != names.end (); ++it) + toplevel_packages[*it] = cdef_manager::find_package (*it, false, true); + + Cell c (toplevel_packages.size (), 1); + + int i = 0; + + for (std::map::const_iterator it = toplevel_packages.begin (); + it != toplevel_packages.end (); ++it) + c(i++,0) = to_ov (it->second); + + return octave_value_list (octave_value (c)); +} + +void +cdef_package::cdef_package_rep::install_class (const cdef_class& cls, + const std::string& nm) +{ + class_map[nm] = cls; + + member_count++; +} + +void +cdef_package::cdef_package_rep::install_function (const octave_value& fcn, + const std::string& nm) +{ + function_map[nm] = fcn; +} + +void +cdef_package::cdef_package_rep::install_package (const cdef_package& pack, + const std::string& nm) +{ + package_map[nm] = pack; + + member_count++; +} + +template +Cell +map2Cell (const std::map& m) +{ + Cell retval (1, m.size ()); + int i = 0; + + for (typename std::map::const_iterator it = m.begin (); + it != m.end (); ++it, ++i) + { + retval(i) = to_ov (it->second); + } + + return retval; +} + +Cell +cdef_package::cdef_package_rep::get_classes (void) const +{ return map2Cell (class_map); } + +Cell +cdef_package::cdef_package_rep::get_functions (void) const +{ return map2Cell (function_map); } + +Cell +cdef_package::cdef_package_rep::get_packages (void) const +{ return map2Cell (package_map); } + +octave_value +cdef_package::cdef_package_rep::find (const std::string& nm) +{ + std::string symbol_name = get_name () + "." + nm; + + return symbol_table::find (symbol_name, octave_value_list (), true, false); +} + +octave_value_list +cdef_package::cdef_package_rep::meta_subsref + (const std::string& type, const std::list& idx, + int nargout) +{ + octave_value_list retval; + + switch (type[0]) + { + case '.': + if (idx.front ().length () == 1) + { + std::string nm = idx.front ()(0).string_value (); + + if (! error_state) + { + gnulib::printf ("meta.package query: %s\n", nm.c_str ()); + + octave_value o = find (nm); + + if (o.is_defined ()) + { + if (o.is_function ()) + { + octave_function* fcn = o.function_value (); + + if (! error_state) + { + if (type.size () == 1 || + ! fcn->is_postfix_index_handled (type[1])) + { + octave_value_list tmp_args; + + retval = o.do_multi_index_op (nargout, + tmp_args); + } + else + retval(0) = o; + + if (type.size () > 1 && idx.size () > 1) + retval = retval(0).next_subsref (nargout, type, + idx, 1); + } + } + else if (type.size () > 1 && idx.size () > 1) + retval = o.next_subsref (nargout, type, idx, 1); + else + retval(0) = o; + } + else + error ("member `%s' in package `%s' does not exist", + nm.c_str (), get_name ().c_str ()); + } + else + error ("invalid meta.package indexing, expected a symbol name"); + } + else + error ("invalid meta.package indexing"); + break; + + default: + error ("invalid meta.package indexing"); + break; + } + + return retval; +} + +void +cdef_package::cdef_package_rep::meta_release (void) +{ + // FIXME: Do we really want to unregister the package, as it + // could still be referenced by classes or sub-packages? + // If the package object is recreated later on, it won't + // match the one already referenced by those classes or + // sub-packages. + + //cdef_manager::unregister_package (wrap ()); +} + +cdef_class cdef_class::_meta_class = cdef_class (); +cdef_class cdef_class::_meta_property = cdef_class (); +cdef_class cdef_class::_meta_method = cdef_class (); +cdef_class cdef_class::_meta_package = cdef_class (); + +cdef_package cdef_package::_meta = cdef_package (); + +void +install_classdef (void) +{ + octave_classdef::register_type (); + + /* bootstrap */ + cdef_class handle = make_class ("handle"); + cdef_class meta_class = cdef_class::_meta_class = make_meta_class ("meta.class", handle); + handle.set_class (meta_class); + meta_class.set_class (meta_class); + + /* meta classes */ + cdef_class meta_property = cdef_class::_meta_property = make_meta_class ("meta.property", handle); + cdef_class meta_method = cdef_class::_meta_method = make_meta_class ("meta.method", handle); + cdef_class meta_package = cdef_class::_meta_package = make_meta_class ("meta.package", handle); + + cdef_class meta_event = make_meta_class ("meta.event", handle); + cdef_class meta_dynproperty = make_meta_class ("meta.dynamicproperty", handle); + + /* meta.class properties */ + meta_class.install_property (make_attribute (meta_class, "Abstract")); + meta_class.install_property (make_attribute (meta_class, "ConstructOnLoad")); + meta_class.install_property (make_property (meta_class, "ContainingPackage")); + meta_class.install_property (make_property (meta_class, "Description")); + meta_class.install_property (make_property (meta_class, "DetailedDescription")); + meta_class.install_property (make_property (meta_class, "Events")); + meta_class.install_property (make_attribute (meta_class, "HandleCompatible")); + meta_class.install_property (make_attribute (meta_class, "Hidden")); + meta_class.install_property + (make_property (meta_class, "InferiorClasses", + make_fcn_handle (class_get_inferiorclasses, "meta.class>get.InferiorClasses"), + "public", Matrix (), "private")); + meta_class.install_property + (make_property (meta_class, "Methods", + make_fcn_handle (class_get_methods, "meta.class>get.Methods"), + "public", Matrix (), "private")); + meta_class.install_property + (make_property (meta_class, "MethodList", + make_fcn_handle (class_get_methods, "meta.class>get.MethodList"), + "public", Matrix (), "private")); + meta_class.install_property (make_attribute (meta_class, "Name")); + meta_class.install_property + (make_property (meta_class, "Properties", + make_fcn_handle (class_get_properties, "meta.class>get.Properties"), + "public", Matrix (), "private")); + meta_class.install_property + (make_property (meta_class, "PropertyList", + make_fcn_handle (class_get_properties, "meta.class>get.PropertyList"), + "public", Matrix (), "private")); + meta_class.install_property (make_attribute (meta_class, "Sealed")); + meta_class.install_property + (make_property (meta_class, "SuperClasses", + make_fcn_handle (class_get_superclasses, "meta.class>get.SuperClasses"), + "public", Matrix (), "private")); + meta_class.install_property + (make_property (meta_class, "SuperClassList", + make_fcn_handle (class_get_superclasses, "meta.class>get.SuperClassList"), + "public", Matrix (), "private")); + /* meta.class methods */ + meta_class.install_method (make_method (meta_class, "fromName", class_fromName, + "public", true)); + meta_class.install_method (make_method (meta_class, "fevalStatic", class_fevalStatic, + "public", false)); + meta_class.install_method (make_method (meta_class, "getConstant", class_getConstant, + "public", false)); + meta_class.install_method (make_method (meta_class, "eq", class_eq)); + meta_class.install_method (make_method (meta_class, "ne", class_ne)); + meta_class.install_method (make_method (meta_class, "lt", class_lt)); + meta_class.install_method (make_method (meta_class, "le", class_le)); + meta_class.install_method (make_method (meta_class, "gt", class_gt)); + meta_class.install_method (make_method (meta_class, "ge", class_ge)); + + /* meta.method properties */ + meta_method.install_property (make_attribute (meta_method, "Abstract")); + meta_method.install_property (make_attribute (meta_method, "Access")); + meta_method.install_property (make_attribute (meta_method, "DefiningClass")); + meta_method.install_property (make_attribute (meta_method, "Description")); + meta_method.install_property (make_attribute (meta_method, "DetailedDescription")); + meta_method.install_property (make_attribute (meta_method, "Hidden")); + meta_method.install_property (make_attribute (meta_method, "Name")); + meta_method.install_property (make_attribute (meta_method, "Sealed")); + meta_method.install_property (make_attribute (meta_method, "Static")); + + /* meta.property properties */ + meta_property.install_property (make_attribute (meta_property, "Name")); + meta_property.install_property (make_attribute (meta_property, "Description")); + meta_property.install_property (make_attribute (meta_property, "DetailedDescription")); + meta_property.install_property (make_attribute (meta_property, "Abstract")); + meta_property.install_property (make_attribute (meta_property, "Constant")); + meta_property.install_property (make_attribute (meta_property, "GetAccess")); + meta_property.install_property (make_attribute (meta_property, "SetAccess")); + meta_property.install_property (make_attribute (meta_property, "Dependent")); + meta_property.install_property (make_attribute (meta_property, "Transient")); + meta_property.install_property (make_attribute (meta_property, "Hidden")); + meta_property.install_property (make_attribute (meta_property, "GetObservable")); + meta_property.install_property (make_attribute (meta_property, "SetObservable")); + meta_property.install_property (make_attribute (meta_property, "GetMethod")); + meta_property.install_property (make_attribute (meta_property, "SetMethod")); + meta_property.install_property (make_attribute (meta_property, "DefiningClass")); + meta_property.install_property + (make_property (meta_property, "DefaultValue", + make_fcn_handle (property_get_defaultvalue, "meta.property>get.DefaultValue"), + "public", Matrix (), "private")); + meta_property.install_property (make_attribute (meta_property, "HasDefault")); + /* meta.property events */ + // FIXME: add events + + /* handle methods */ + handle.install_method (make_method (handle, "delete", handle_delete)); + + /* meta.package properties */ + meta_package.install_property (make_attribute (meta_package, "Name")); + meta_package.install_property (make_property (meta_package, "ContainingPackage")); + meta_package.install_property + (make_property (meta_package, "ClassList", + make_fcn_handle (package_get_classes, "meta.package>get.ClassList"), + "public", Matrix (), "private")); + meta_package.install_property + (make_property (meta_package, "Classes", + make_fcn_handle (package_get_classes, "meta.package>get.Classes"), + "public", Matrix (), "private")); + meta_package.install_property + (make_property (meta_package, "FunctionList", + make_fcn_handle (package_get_functions, "meta.package>get.FunctionList"), + "public", Matrix (), "private")); + meta_package.install_property + (make_property (meta_package, "Functions", + make_fcn_handle (package_get_functions, "meta.package>get.Functions"), + "public", Matrix (), "private")); + meta_package.install_property + (make_property (meta_package, "PackageList", + make_fcn_handle (package_get_packages, "meta.package>get.PackageList"), + "public", Matrix (), "private")); + meta_package.install_property + (make_property (meta_package, "Packages", + make_fcn_handle (package_get_packages, "meta.package>get.Packages"), + "public", Matrix (), "private")); + meta_package.install_method (make_method (meta_package, "fromName", package_fromName, + "public", true)); + meta_package.install_method (make_method (meta_package, "getAllPackages", package_getAllPackages, + "public", true)); + + /* create "meta" package */ + cdef_package package_meta = cdef_package::_meta = make_package ("meta"); + package_meta.install_class (meta_class, "class"); + package_meta.install_class (meta_property, "property"); + package_meta.install_class (meta_method, "method"); + package_meta.install_class (meta_package, "package"); + package_meta.install_class (meta_event, "event"); + package_meta.install_class (meta_dynproperty, "dynproperty"); + + /* install built-in classes into the symbol table */ + symbol_table::install_built_in_function + ("meta.class", octave_value (meta_class.get_constructor_function ())); + symbol_table::install_built_in_function + ("meta.method", octave_value (meta_method.get_constructor_function ())); + symbol_table::install_built_in_function + ("meta.property", octave_value (meta_property.get_constructor_function ())); + symbol_table::install_built_in_function + ("meta.package", octave_value (meta_package.get_constructor_function ())); + symbol_table::install_built_in_function + ("meta.event", octave_value (meta_event.get_constructor_function ())); + symbol_table::install_built_in_function + ("meta.dynproperty", octave_value (meta_dynproperty.get_constructor_function ())); +} + +//---------------------------------------------------------------------------- + +cdef_manager* cdef_manager::instance = 0; + +void +cdef_manager::create_instance (void) +{ + instance = new cdef_manager (); + + if (instance) + singleton_cleanup_list::add (cleanup_instance); +} + +cdef_class +cdef_manager::do_find_class (const std::string& name, + bool error_if_not_found, bool load_if_not_found) +{ + std::map::iterator it = all_classes.find (name); + + if (it == all_classes.end ()) + { + if (load_if_not_found) + { + octave_value ov_cls; + + size_t pos = name.rfind ('.'); + + if (pos == std::string::npos) + ov_cls = symbol_table::find (name); + else + { + std::string pack_name = name.substr (0, pos); + + cdef_package pack = do_find_package (pack_name, false, true); + + if (pack.ok ()) + ov_cls = pack.find (name.substr (pos+1)); + } + + if (ov_cls.is_defined ()) + it = all_classes.find (name); + } + } + + if (it == all_classes.end ()) + { + if (error_if_not_found) + error ("class not found: %s", name.c_str ()); + } + else + { + cdef_class cls = it->second; + + if (! cls.is_builtin ()) + cls = lookup_class (cls); + + if (cls.ok ()) + return cls; + else + all_classes.erase (it); + } + + return cdef_class (); +} + +octave_function* +cdef_manager::do_find_method_symbol (const std::string& method_name, + const std::string& class_name) +{ + octave_function *retval = 0; + + cdef_class cls = find_class (class_name, false, false); + + if (cls.ok ()) + { + cdef_method meth = cls.find_method (method_name); + + if (meth.ok ()) + retval = new octave_classdef_meta (meth); + } + + return retval; +} + +cdef_package +cdef_manager::do_find_package (const std::string& name, + bool error_if_not_found, + bool load_if_not_found) +{ + cdef_package retval; + + std::map::const_iterator it + = all_packages.find (name); + + if (it != all_packages.end ()) + { + retval = it->second; + + if (! retval.ok ()) + error ("invalid package `%s'", name.c_str ()); + } + else + { + if (load_if_not_found && load_path::find_package (name)) + { + size_t pos = name.find ('.'); + + if (pos == std::string::npos) + retval = make_package (name, std::string ()); + else + { + std::string parent_name = name.substr (0, pos); + + retval = make_package (name, parent_name); + } + } + else if (error_if_not_found) + error ("unknown package `%s'", name.c_str ()); + } + + return retval; +} + +octave_function* +cdef_manager::do_find_package_symbol (const std::string& pack_name) +{ + octave_function* retval = 0; + + cdef_package pack = find_package (pack_name, false); + + if (pack.ok ()) + retval = new octave_classdef_meta (pack); + + return retval; +} + +//---------------------------------------------------------------------------- + +DEFUN (__meta_get_package__, args, , "") +{ + octave_value retval; + + if (args.length () == 1) + { + std::string cname = args(0).string_value (); + + if (! error_state) + retval = to_ov (lookup_package (cname)); + else + error ("invalid package name, expected a string value"); + } + else + print_usage (); + + return retval; +} + +DEFUN (__superclass_reference__, args, /* nargout */, + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} __superclass_reference__ ()\n\ +Undocumented internal function.\n\ +@end deftypefn") +{ + return octave_value (new octave_classdef_superclass_ref (args)); +} + +DEFUN (__meta_class_query__, args, /* nargout */, + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} __meta_class_query__ ()\n\ +Undocumented internal function.\n\ +@end deftypefn") +{ + octave_value retval; + + std::cerr << "__meta_class_query__ (" + << args(0).string_value () << ", " + << args(1).string_value () << ")" + << std::endl; + + if (args.length () == 2) + { + std::string pkg = args(0).string_value (); + std::string cls = args(1).string_value (); + + if (! pkg.empty ()) + cls = pkg + "." + cls; + + if (! error_state) + retval = to_ov (lookup_class (cls)); + else + error ("invalid class name, expected a string value"); + } + else + print_usage (); + + return retval; +} + +DEFUN (metaclass, args, /* nargout */, + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} metaclass (obj)\n\ +Returns the meta.class object corresponding to the class of @var{obj}.\n\ +@end deftypefn") +{ + octave_value retval; + + if (args.length () == 1) + { + cdef_object obj = to_cdef (args(0)); + + if (! error_state) + retval = to_ov (obj.get_class ()); + else + print_usage (); + } + else + print_usage (); + + return retval; +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-classdef.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/octave-value/ov-classdef.h Tue Jan 07 16:07:54 2014 -0500 @@ -0,0 +1,1653 @@ +/* + +Copyright (C) 2012-2013 Michael Goffioul + +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 +. + +*/ + +#if !defined (octave_classdef_h) +#define octave_classdef_h 1 + +#include +#include +#include + +#include "oct-map.h" +#include "oct-refcount.h" +#include "ov-base.h" +#include "symtab.h" + +class cdef_object; +class cdef_class; +class cdef_property; +class cdef_method; +class cdef_package; + +class tree_classdef; + +// This is mainly a boostrap class to declare the expected interface. +// The actual base class is cdef_class_base, which is declared after +// cdef_object, such that it can contain cdef_object objects. +class +cdef_object_rep +{ +public: + friend class cdef_object; + +public: + cdef_object_rep (void) : refcount (1) { } + + virtual ~cdef_object_rep (void) { } + + virtual cdef_class get_class (void) const; + + virtual void set_class (const cdef_class&) + { gripe_invalid_object ("set_class"); } + + virtual cdef_object_rep* clone (void) const + { + gripe_invalid_object ("clone"); + return new cdef_object_rep (); + } + + virtual cdef_object_rep* empty_clone (void) const + { + gripe_invalid_object ("empty_clone"); + return new cdef_object_rep (); + } + + virtual cdef_object_rep* copy (void) const + { + gripe_invalid_object ("copy"); + return new cdef_object_rep (); + } + + virtual cdef_object_rep* make_array (void) const + { + gripe_invalid_object ("make_array"); + return new cdef_object_rep (); + } + + virtual bool is_array (void) const { return false; } + + virtual bool is_value_object (void) const { return false; } + + virtual bool is_handle_object (void) const { return false; } + + virtual bool is_meta_object (void) const { return false; } + + virtual Array array_value (void) const + { + gripe_invalid_object ("array_value"); + return Array (); + } + + virtual void put (const std::string&, const octave_value&) + { gripe_invalid_object ("put"); } + + virtual octave_value get (const std::string&) const + { + gripe_invalid_object ("get"); + return octave_value (); + } + + virtual octave_value_list + subsref (const std::string&, const std::list&, + int, size_t&, const cdef_class&, bool) + { + gripe_invalid_object ("subsref"); + return octave_value_list (); + } + + virtual octave_value + subsasgn (const std::string&, const std::list&, + const octave_value&) + { + gripe_invalid_object ("subsasgn"); + return octave_value (); + } + + virtual string_vector map_keys(void) const; + + virtual bool is_valid (void) const { return false; } + + std::string class_name (void) const; + + virtual void mark_for_construction (const cdef_class&) + { gripe_invalid_object ("mark_for_construction"); } + + virtual bool is_constructed_for (const cdef_class&) const + { + gripe_invalid_object ("is_constructed_for"); + return false; + } + + virtual bool is_partially_constructed_for (const cdef_class&) const + { + gripe_invalid_object ("is_partially_constructed_for"); + return false; + } + + virtual void mark_as_constructed (void) + { gripe_invalid_object ("mark_as_constructed"); } + + virtual void mark_as_constructed (const cdef_class&) + { gripe_invalid_object ("mark_as_constructed"); } + + virtual bool is_constructed (void) const + { + gripe_invalid_object ("is_constructed"); + return false; + } + + virtual octave_idx_type static_count (void) const { return 0; } + + virtual void destroy (void) { delete this; } + + void release (void) + { + if (--refcount == static_count ()) + destroy (); + } + + virtual dim_vector dims (void) const { return dim_vector (); } + +protected: + /* reference count */ + octave_refcount refcount; + +protected: + /* Restricted copying */ + cdef_object_rep (const cdef_object_rep&) + : refcount (1) { } + +private: + /* No assignment */ + cdef_object_rep& operator = (const cdef_object_rep& ); + + void gripe_invalid_object (const char *who) const + { error ("%s: invalid object", who); } +}; + +class +cdef_object +{ +public: + /* FIXME: use a null object */ + cdef_object (void) + : rep (new cdef_object_rep ()) { } + + cdef_object (const cdef_object& obj) + : rep (obj.rep) + { + rep->refcount++; + } + + cdef_object (cdef_object_rep *r) + : rep (r) { } + + virtual ~cdef_object (void) + { rep->release (); } + + cdef_object& operator = (const cdef_object& obj) + { + if (rep != obj.rep) + { + rep->release (); + + rep = obj.rep; + rep->refcount++; + } + + return *this; + } + + cdef_class get_class (void) const; + + void set_class (const cdef_class& cls) { rep->set_class (cls); } + + std::string class_name (void) const + { return rep->class_name (); } + + cdef_object clone (void) const + { return cdef_object (rep->clone ()); } + + cdef_object empty_clone (void) const + { return cdef_object (rep->empty_clone ()); } + + dim_vector dims (void) const { return rep->dims (); } + + cdef_object make_array (void) const + { return cdef_object (rep->make_array ()); } + + cdef_object copy (void) const + { return cdef_object (rep->copy ()); } + + bool is_array (void) const { return rep->is_array (); } + + bool is_value_object (void) const { return rep->is_value_object (); } + + bool is_handle_object (void) const { return rep->is_handle_object (); } + + bool is_meta_object (void) const { return rep->is_meta_object (); } + + Array array_value (void) const { return rep->array_value (); } + + void put (const std::string& pname, const octave_value& val) + { rep->put (pname, val); } + + octave_value get (const std::string& pname) const + { return rep->get (pname); } + + octave_value_list + subsref (const std::string& type, const std::list& idx, + int nargout, size_t& skip, const cdef_class& context, + bool auto_add = false) + { return rep->subsref (type, idx, nargout, skip, context, auto_add); } + + octave_value + subsasgn (const std::string& type, const std::list& idx, + const octave_value& rhs, int ignore_copies = 0) + { + make_unique (ignore_copies); + return rep->subsasgn (type, idx, rhs); + } + + string_vector map_keys (void) const { return rep->map_keys (); } + + const cdef_object_rep* get_rep (void) const { return rep; } + + bool ok (void) const { return rep->is_valid (); } + + void mark_for_construction (const cdef_class& cls) + { rep->mark_for_construction (cls); } + + bool is_constructed (void) const { return rep->is_constructed (); } + + bool is_constructed_for (const cdef_class& cls) const + { return rep->is_constructed_for (cls); } + + bool is_partially_constructed_for (const cdef_class& cls) const + { return rep->is_partially_constructed_for (cls); } + + void mark_as_constructed (void) { rep->mark_as_constructed (); } + + void mark_as_constructed (const cdef_class& cls) + { rep->mark_as_constructed (cls); } + + bool is (const cdef_object& obj) const { return rep == obj.rep; } + +protected: + cdef_object_rep* get_rep (void) { return rep; } + + void make_unique (int ignore_copies) + { + if (rep->refcount > ignore_copies + 1) + *this = clone (); + } + +private: + cdef_object_rep *rep; +}; + +class +cdef_object_base : public cdef_object_rep +{ +public: + cdef_object_base (void) + : cdef_object_rep (), klass () + { + register_object (); + } + + ~cdef_object_base (void) { unregister_object (); } + + cdef_class get_class (void) const; + + void set_class (const cdef_class& cls); + + cdef_object_rep* empty_clone (void) const + { return new cdef_object_base (*this); } + + cdef_object_rep* make_array (void) const; + +protected: + // Restricted copying! + cdef_object_base (const cdef_object_base& obj) + : cdef_object_rep (obj), klass (obj.klass) + { + register_object (); + } + +private: + void register_object (void); + + void unregister_object (void); + +private: + // The class of the object + cdef_object klass; + +private: + // No assignment! + cdef_object_base& operator = (const cdef_object_base&); +}; + +class +cdef_object_array : public cdef_object_base +{ +public: + cdef_object_array (void) : cdef_object_base () { } + + cdef_object_array (const Array& a) + : cdef_object_base (), array (a) { } + + cdef_object_rep* clone (void) const + { return new cdef_object_array (*this); } + + dim_vector dims (void) const { return array.dims (); } + + bool is_valid (void) const { return true; } + + bool is_array (void) const { return true; } + + Array array_value (void) const { return array; } + + octave_value_list + subsref (const std::string& type, const std::list& idx, + int nargout, size_t& skip, const cdef_class& context, + bool auto_add); + + octave_value + subsasgn (const std::string& type, const std::list& idx, + const octave_value& rhs); + +private: + Array array; + +private: + void fill_empty_values (void) { fill_empty_values (array); } + + void fill_empty_values (Array& arr); + + // Private copying! + cdef_object_array (const cdef_object_array& obj) + : cdef_object_base (obj), array (obj.array) { } + + // No assignment! + cdef_object_array& operator = (const cdef_object_array&); +}; + +class +cdef_object_scalar : public cdef_object_base +{ +public: + cdef_object_scalar (void) : cdef_object_base () { } + + ~cdef_object_scalar (void) { } + + dim_vector dims (void) const { return dim_vector (1, 1); } + + void put (const std::string& pname, const octave_value& val) + { map.assign (pname, val); } + + octave_value get (const std::string& pname) const + { + Cell val = map.contents (pname); + + if (val.numel () > 0) + return val(0, 0); + else + { + error ("get: unknown slot: %s", pname.c_str ()); + return octave_value (); + } + } + + octave_value_list + subsref (const std::string& type, const std::list& idx, + int nargout, size_t& skip, const cdef_class& context, + bool auto_add); + + octave_value + subsasgn (const std::string& type, const std::list& idx, + const octave_value& rhs); + + void mark_for_construction (const cdef_class&); + + bool is_constructed_for (const cdef_class& cls) const; + + bool is_partially_constructed_for (const cdef_class& cls) const; + + void mark_as_constructed (void) { ctor_list.clear (); } + + void mark_as_constructed (const cdef_class& cls) { ctor_list.erase (cls); } + + bool is_constructed (void) const { return ctor_list.empty (); } + +protected: + // Object property values + Octave_map map; + + // Internal/temporary structure used during object construction + std::map< cdef_class, std::list > ctor_list; + +protected: + // Restricted object copying! + cdef_object_scalar (const cdef_object_scalar& obj) + : cdef_object_base (obj), map (obj.map), ctor_list (obj.ctor_list) { } + +private: + // No assignment! + cdef_object_scalar& operator = (const cdef_object_scalar&); +}; + +class +handle_cdef_object : public cdef_object_scalar +{ +public: + handle_cdef_object (void) + : cdef_object_scalar () { } + + ~handle_cdef_object (void); + + cdef_object_rep* clone (void) const + { + handle_cdef_object *obj = const_cast (this); + obj->refcount++; + return obj; + } + + cdef_object_rep* copy (void) const + { return new handle_cdef_object (*this); } + + bool is_valid (void) const { return true; } + + bool is_handle_object (void) const { return true; } + +protected: + // Restricted copying! + handle_cdef_object (const handle_cdef_object& obj) + : cdef_object_scalar (obj) { } + +private: + // No assignment + handle_cdef_object& operator = (const handle_cdef_object&); +}; + +class +value_cdef_object : public cdef_object_scalar +{ +public: + value_cdef_object (void) + : cdef_object_scalar () { } + + ~value_cdef_object (void); + + cdef_object_rep* clone (void) const + { return new value_cdef_object (*this); } + + cdef_object_rep* copy (void) const { return clone (); } + + bool is_valid (void) const { return true; } + + bool is_value_object (void) const { return true; } + +private: + // Private copying! + value_cdef_object (const value_cdef_object& obj) + : cdef_object_scalar (obj) { } + + // No assignment! + value_cdef_object& operator = (const value_cdef_object&); +}; + +class +cdef_meta_object_rep : public handle_cdef_object +{ +public: + cdef_meta_object_rep (void) + : handle_cdef_object () { } + + ~cdef_meta_object_rep (void) { } + + cdef_object_rep* copy (void) const + { return new cdef_meta_object_rep (*this); } + + bool is_meta_object (void) const { return true; } + + virtual bool is_class (void) const { return false; } + + virtual bool is_property (void) const { return false; } + + virtual bool is_method (void) const { return false; } + + virtual bool is_package (void) const { return false; } + + virtual octave_value_list + meta_subsref (const std::string& /* type */, + const std::list& /* idx */, + int /* nargout */) + { + ::error ("subsref: invalid meta object"); + return octave_value_list (); + } + + virtual void meta_release (void) { } + + virtual bool meta_is_postfix_index_handled (char /* type */) const + { return false; } + +protected: + // Restricted copying! + cdef_meta_object_rep (const cdef_meta_object_rep& obj) + : handle_cdef_object (obj) { } + +private: + // No assignment! + cdef_meta_object_rep& operator = (const cdef_meta_object_rep&); +}; + +class +cdef_meta_object : public cdef_object +{ +public: + cdef_meta_object (void) + : cdef_object () { } + + cdef_meta_object (const cdef_meta_object& obj) + : cdef_object (obj) { } + + cdef_meta_object (cdef_meta_object_rep *r) + : cdef_object (r) { } + + // Object consistency is checked in sub-classes. + cdef_meta_object (const cdef_object& obj) + : cdef_object (obj) { } + + ~cdef_meta_object (void) { } + + bool is_class (void) const { return get_rep ()->is_class (); } + + bool is_property (void) const { return get_rep ()->is_property (); } + + bool is_method (void) const { return get_rep ()->is_method (); } + + bool is_package (void) const { return get_rep ()->is_package (); } + + octave_value_list + meta_subsref (const std::string& type, + const std::list& idx, int nargout) + { return get_rep ()->meta_subsref (type, idx, nargout); } + + void meta_release (void) { get_rep ()->meta_release (); } + + bool meta_is_postfix_index_handled (char type) const + { return get_rep ()->meta_is_postfix_index_handled (type); } + +private: + cdef_meta_object_rep* get_rep (void) + { return dynamic_cast (cdef_object::get_rep ()); } + + const cdef_meta_object_rep* get_rep (void) const + { return dynamic_cast (cdef_object::get_rep ()); } +}; + +class +cdef_class : public cdef_meta_object +{ +private: + + class + cdef_class_rep : public cdef_meta_object_rep + { + public: + cdef_class_rep (void) + : cdef_meta_object_rep (), member_count (0), handle_class (false), + object_count (0), meta (false) { } + + cdef_class_rep (const std::list& superclasses); + + cdef_object_rep* copy (void) const { return new cdef_class_rep (*this); } + + bool is_class (void) const { return true; } + + std::string get_name (void) const + { return get ("Name").string_value (); } + + void set_name (const std::string& nm) { put ("Name", nm); } + + bool is_abstract (void) const { return get ("Abstract").bool_value (); } + + bool is_sealed (void) const { return get ("Sealed").bool_value (); } + + cdef_method find_method (const std::string& nm, bool local = false); + + void install_method (const cdef_method& meth); + + Cell get_methods (void); + + cdef_property find_property (const std::string& nm); + + void install_property (const cdef_property& prop); + + Cell get_properties (void); + + string_vector get_names (void); + + void set_directory (const std::string& dir) { directory = dir; } + + std::string get_directory (void) const { return directory; } + + void delete_object (cdef_object obj); + + octave_value_list + meta_subsref (const std::string& type, + const std::list& idx, int nargout); + + void meta_release (void); + + bool meta_is_postfix_index_handled (char type) const + { return (type == '(' || type == '.'); } + + octave_value construct (const octave_value_list& args); + + cdef_object construct_object (const octave_value_list& args); + + void initialize_object (cdef_object& obj); + + void run_constructor (cdef_object& obj, const octave_value_list& args); + + void mark_as_handle_class (void) { handle_class = true; } + + bool is_handle_class (void) const { return handle_class; } + + void register_object (void) { object_count++; } + + void unregister_object (void) { object_count--; } + + octave_idx_type static_count (void) const { return member_count; } + + void destroy (void) + { + if (member_count) + { + refcount++; + cdef_class lock (this); + + member_count = 0; + method_map.clear (); + property_map.clear (); + } + else + delete this; + } + + void mark_as_meta_class (void) { meta = true; } + + bool is_meta_class (void) const { return meta; } + + private: + void load_all_methods (void); + + void find_names (std::set& names, bool all); + + void find_properties (std::map& props, + bool only_inherited); + + void find_methods (std::map& meths, + bool only_inherited); + + cdef_class wrap (void) + { + refcount++; + return cdef_class (this); + } + + private: + // The @-directory were this class is loaded from. + // (not used yet) + std::string directory; + + // The methods defined by this class. + std::map method_map; + + // The properties defined by this class. + std::map property_map; + + // The number of members in this class (methods, properties...) + octave_idx_type member_count; + + // TRUE if this class is a handle class. A class is a handle + // class when the abstract "handle" class is one of its superclasses. + bool handle_class; + + // The list of super-class constructors that are called implicitly by the + // the classdef engine when creating an object. These constructors are not + // called explicitly by the class constructor. + std::list implicit_ctor_list; + + // The number of objects of this class. + octave_refcount object_count; + + // TRUE if this class is a built-in meta class. + bool meta; + + // Utility iterator typedef's. + typedef std::map::iterator method_iterator; + typedef std::map::const_iterator method_const_iterator; + typedef std::map::iterator property_iterator; + typedef std::map::const_iterator property_const_iterator; + + private: + cdef_class_rep (const cdef_class_rep& c) + : cdef_meta_object_rep (c), directory (c.directory), + method_map (c.method_map), property_map (c.property_map), + member_count (c.member_count), handle_class (c.handle_class), + implicit_ctor_list (c.implicit_ctor_list), + object_count (c.object_count), meta (c.meta) { } + }; + +public: + // Create and invalid class object + cdef_class (void) + : cdef_meta_object () { } + + cdef_class (const std::string& nm, + const std::list& superclasses) + : cdef_meta_object (new cdef_class_rep (superclasses)) + { get_rep ()->set_name (nm); } + + cdef_class (const cdef_class& cls) + : cdef_meta_object (cls) { } + + cdef_class (const cdef_object& obj) + : cdef_meta_object (obj) + { + // This should never happen... + if (! is_class ()) + error ("internal error: invalid assignment from %s to meta.class object", + class_name ().c_str ()); + } + + cdef_class& operator = (const cdef_class& cls) + { + cdef_object::operator= (cls); + + return *this; + } + + cdef_method find_method (const std::string& nm, bool local = false); + + void install_method (const cdef_method& meth) + { get_rep ()->install_method (meth); } + + Cell get_methods (void) { return get_rep ()->get_methods (); } + + cdef_property find_property (const std::string& nm); + + void install_property (const cdef_property& prop) + { get_rep ()->install_property (prop); } + + Cell get_properties (void) { return get_rep ()->get_properties (); } + + string_vector get_names (void) { return get_rep ()->get_names (); } + + bool is_abstract (void) const { return get_rep ()->is_abstract (); } + + bool is_sealed (void) const { return get_rep ()->is_sealed (); } + + void set_directory (const std::string& dir) + { get_rep ()->set_directory (dir); } + + std::string get_directory (void) const + { return get_rep ()->get_directory (); } + + std::string get_name (void) const + { return get_rep ()->get_name (); } + + bool is_builtin (void) const + { return get_directory ().empty (); } + + void delete_object (cdef_object obj) + { get_rep ()->delete_object (obj); } + + static cdef_class make_meta_class (tree_classdef* t); + + octave_function* get_method_function (const std::string& nm); + + octave_function* get_constructor_function (void) + { return get_method_function (get_name ()); } + + octave_value construct (const octave_value_list& args) + { return get_rep ()->construct (args); } + + cdef_object construct_object (const octave_value_list& args) + { return get_rep ()->construct_object (args); } + + void initialize_object (cdef_object& obj) + { get_rep ()->initialize_object (obj); } + + void run_constructor (cdef_object& obj, const octave_value_list& args) + { get_rep ()->run_constructor (obj, args); } + + void mark_as_handle_class (void) + { get_rep ()->mark_as_handle_class (); } + + bool is_handle_class (void) const + { return get_rep ()->is_handle_class (); } + + void mark_as_meta_class (void) { get_rep ()->mark_as_meta_class (); } + + bool is_meta_class (void) const { return get_rep ()->is_meta_class (); } + + static const cdef_class& meta_class (void) { return _meta_class; } + static const cdef_class& meta_property (void) { return _meta_property; } + static const cdef_class& meta_method (void) { return _meta_method; } + static const cdef_class& meta_package (void) { return _meta_package; } + + void register_object (void) { get_rep ()->register_object (); } + + void unregister_object (void) { get_rep ()->unregister_object (); } + +private: + cdef_class_rep* get_rep (void) + { return dynamic_cast (cdef_object::get_rep ()); } + + const cdef_class_rep* get_rep (void) const + { return dynamic_cast (cdef_object::get_rep ()); } + + friend bool operator == (const cdef_class&, const cdef_class&); + friend bool operator != (const cdef_class&, const cdef_class&); + friend bool operator < (const cdef_class&, const cdef_class&); + +private: + static cdef_class _meta_class; + static cdef_class _meta_property; + static cdef_class _meta_method; + static cdef_class _meta_package; + + friend void install_classdef (void); +}; + +inline bool +operator == (const cdef_class& clsa, const cdef_class& clsb) +// FIXME: is this really the right way to check class equality? +{ return (clsa.get_rep () == clsb.get_rep ()); } + +inline bool +operator != (const cdef_class& clsa, const cdef_class& clsb) +{ return ! (clsa == clsb); } + +// This is only to be able to use cdef_class as map keys. +inline bool +operator < (const cdef_class& clsa, const cdef_class& clsb) +{ return clsa.get_rep () < clsb.get_rep (); } + +class +cdef_property : public cdef_meta_object +{ + friend class cdef_class; + +private: + + class + cdef_property_rep : public cdef_meta_object_rep + { + public: + cdef_property_rep (void) + : cdef_meta_object_rep () { } + + cdef_object_rep* copy (void) const { return new cdef_property_rep (*this); } + + bool is_property (void) const { return true; } + + std::string get_name (void) const { return get("Name").string_value (); } + + void set_name (const std::string& nm) { put ("Name", nm); } + + bool is_constant (void) const { return get("Constant").bool_value (); } + + octave_value get_value (bool do_check_access = true, + const std::string& who = std::string ()); + + octave_value get_value (const cdef_object& obj, + bool do_check_access = true, + const std::string& who = std::string ()); + + void set_value (cdef_object& obj, const octave_value& val, + bool do_check_access = true, + const std::string& who = std::string ()); + + bool check_get_access (void) const; + + bool check_set_access (void) const; + + private: + cdef_property_rep (const cdef_property_rep& p) + : cdef_meta_object_rep (p) { } + + bool is_recursive_set (const cdef_object& obj) const; + + cdef_property wrap (void) + { + refcount++; + return cdef_property (this); + } + }; + +public: + cdef_property (void) : cdef_meta_object () { } + + cdef_property (const std::string& nm) + : cdef_meta_object (new cdef_property_rep ()) + { get_rep ()->set_name (nm); } + + cdef_property (const cdef_property& prop) + : cdef_meta_object (prop) { } + + cdef_property (const cdef_object& obj) + : cdef_meta_object (obj) + { + // This should never happen... + if (! is_property ()) + error ("internal error: invalid assignment from %s to meta.property object", + class_name ().c_str ()); + } + + cdef_property& operator = (const cdef_property& prop) + { + cdef_object::operator= (prop); + + return *this; + } + + octave_value get_value (const cdef_object& obj, bool do_check_access = true, + const std::string& who = std::string ()) + { return get_rep ()->get_value (obj, do_check_access, who); } + + octave_value get_value (bool do_check_access = true, + const std::string& who = std::string ()) + { return get_rep ()->get_value (do_check_access, who); } + + void set_value (cdef_object& obj, const octave_value& val, + bool do_check_access = true, + const std::string& who = std::string ()) + { get_rep ()->set_value (obj, val, do_check_access, who); } + + bool check_get_access (void) const + { return get_rep ()->check_get_access (); } + + bool check_set_access (void) const + { return get_rep ()->check_set_access (); } + + std::string get_name (void) const { return get_rep ()->get_name (); } + + bool is_constant (void) const { return get_rep ()->is_constant (); } + +private: + cdef_property_rep* get_rep (void) + { return dynamic_cast (cdef_object::get_rep ()); } + + const cdef_property_rep* get_rep (void) const + { return dynamic_cast (cdef_object::get_rep ()); } +}; + +class +cdef_method : public cdef_meta_object +{ + friend class cdef_class; + +private: + + class + cdef_method_rep : public cdef_meta_object_rep + { + public: + cdef_method_rep (void) : cdef_meta_object_rep () { } + + cdef_object_rep* copy (void) const { return new cdef_method_rep(*this); } + + bool is_method (void) const { return true; } + + std::string get_name (void) const { return get("Name").string_value (); } + + void set_name (const std::string& nm) { put ("Name", nm); } + + bool is_static (void) const { return get("Static").bool_value (); } + + octave_value get_function (void) const { return function; } + + void set_function (const octave_value& fcn) { function = fcn; } + + bool check_access (void) const; + + octave_value_list execute (const octave_value_list& args, int nargout, + bool do_check_access = true, + const std::string& who = std::string ()); + + octave_value_list execute (const cdef_object& obj, + const octave_value_list& args, int nargout, + bool do_check_access = true, + const std::string& who = std::string ()); + + bool is_constructor (void) const; + + octave_value_list + meta_subsref (const std::string& type, + const std::list& idx, int nargout); + + bool meta_is_postfix_index_handled (char type) const + { return (type == '(' || type == '.'); } + + private: + cdef_method_rep (const cdef_method_rep& m) + : cdef_meta_object_rep (m), function (m.function) { } + + void check_method (void); + + cdef_method wrap (void) + { + refcount++; + return cdef_method (this); + } + + private: + octave_value function; + }; + +public: + cdef_method (void) : cdef_meta_object () { } + + cdef_method (const std::string& nm) + : cdef_meta_object (new cdef_method_rep ()) + { get_rep ()->set_name (nm); } + + cdef_method (const cdef_method& meth) + : cdef_meta_object (meth) { } + + cdef_method (const cdef_object& obj) + : cdef_meta_object (obj) + { + // This should never happen... + if (! is_method ()) + error ("internal error: invalid assignment from %s to meta.method object", + class_name ().c_str ()); + } + + cdef_method& operator = (const cdef_method& meth) + { + cdef_object::operator= (meth); + + return *this; + } + + /* normal invokation */ + octave_value_list execute (const octave_value_list& args, int nargout, + bool do_check_access = true, + const std::string& who = std::string ()) + { return get_rep ()->execute (args, nargout, do_check_access, who); } + + /* dot-invokation: object is pushed as 1st argument */ + octave_value_list execute (const cdef_object& obj, + const octave_value_list& args, int nargout, + bool do_check_access = true, + const std::string& who = std::string ()) + { return get_rep ()->execute (obj, args, nargout, do_check_access, who); } + + bool check_access (void) const { return get_rep ()->check_access (); } + + std::string get_name (void) const { return get_rep ()->get_name (); } + + bool is_static (void) const { return get_rep ()->is_static (); } + + void set_function (const octave_value& fcn) + { get_rep ()->set_function (fcn); } + + octave_value get_function (void) const + { return get_rep ()->get_function (); } + + bool is_constructor (void) const + { return get_rep ()->is_constructor (); } + +private: + cdef_method_rep* get_rep (void) + { return dynamic_cast (cdef_object::get_rep ()); } + + const cdef_method_rep* get_rep (void) const + { return dynamic_cast (cdef_object::get_rep ()); } +}; + +inline cdef_class +cdef_object_rep::get_class (void) const +{ + gripe_invalid_object ("get_class"); + return cdef_class (); +} + +inline std::string +cdef_object_rep::class_name (void) const +{ return get_class ().get_name (); } + +inline cdef_class +cdef_object::get_class (void) const +{ return rep->get_class (); } + +inline cdef_class +cdef_object_base::get_class (void) const +{ return cdef_class (klass); } + +inline void +cdef_object_base::set_class (const cdef_class& cls) +{ + if ((klass.ok () && cls.ok () && cls != get_class ()) + || (klass.ok () && ! cls.ok ()) + || (! klass.ok () && cls.ok ())) + { + unregister_object (); + klass = cls; + register_object (); + } +} + +inline void +cdef_object_base::register_object (void) +{ + if (klass.ok ()) + { + cdef_class cls (get_class ()); + + if (! error_state && cls.ok ()) + cls.register_object (); + } +} + +inline void +cdef_object_base::unregister_object (void) +{ + if (klass.ok ()) + { + cdef_class cls (get_class ()); + + if (! error_state && cls.ok ()) + cls.unregister_object (); + } +} + +inline cdef_object_rep* +cdef_object_base::make_array (void) const +{ + cdef_object_rep* r = new cdef_object_array (); + + r->set_class (get_class ()); + + return r; +} + +inline cdef_method +cdef_class::find_method (const std::string& nm, bool local) +{ return get_rep ()->find_method (nm, local); } + +inline cdef_property +cdef_class::find_property (const std::string& nm) +{ return get_rep ()->find_property (nm); } + +class +cdef_package : public cdef_meta_object +{ + friend class cdef_class; + +private: + + class + cdef_package_rep : public cdef_meta_object_rep + { + public: + cdef_package_rep (void) + : cdef_meta_object_rep (), member_count (0) { } + + ~cdef_package_rep (void) { } + + cdef_object_rep* copy (void) const { return new cdef_package_rep (*this); } + + bool is_package (void) const { return true; } + + std::string get_name (void) const { return get("Name").string_value (); } + + void set_name (const std::string& nm) { put ("Name", nm); } + + void install_class (const cdef_class& cls, const std::string& nm); + + void install_function (const octave_value& fcn, const std::string& nm); + + void install_package (const cdef_package& pack, const std::string& nm); + + Cell get_classes (void) const; + + Cell get_functions (void) const; + + Cell get_packages (void) const; + + octave_idx_type static_count (void) const { return member_count; } + + void destroy (void) + { + if (member_count) + { + refcount++; + cdef_package lock (this); + + member_count = 0; + class_map.clear (); + package_map.clear (); + } + else + delete this; + } + + octave_value_list + meta_subsref (const std::string& type, + const std::list& idx, int nargout); + + void meta_release (void); + + bool meta_is_postfix_index_handled (char type) const + { return (type == '.'); } + + octave_value find (const std::string& nm); + + private: + std::string full_name; + std::map class_map; + std::map function_map; + std::map package_map; + + // The number of registered members in this package (classes, packages). + // This only accounts for the members that back-reference to this package. + octave_idx_type member_count; + + typedef std::map::iterator class_iterator; + typedef std::map::const_iterator class_const_iterator; + typedef std::map::iterator function_iterator; + typedef std::map::const_iterator function_const_iterator; + typedef std::map::iterator package_iterator; + typedef std::map::const_iterator package_const_iterator; + + private: + cdef_package_rep (const cdef_package_rep& p) + : cdef_meta_object_rep (p), full_name (p.full_name), + class_map (p.class_map), function_map (p.function_map), + package_map (p.package_map), member_count (p.member_count) + { } + + cdef_package wrap (void) + { + refcount++; + return cdef_package (this); + } + }; + +public: + cdef_package (void) : cdef_meta_object () { } + + cdef_package (const std::string& nm) + : cdef_meta_object (new cdef_package_rep ()) + { get_rep ()->set_name (nm); } + + cdef_package (const cdef_package& pack) + : cdef_meta_object (pack) { } + + cdef_package (const cdef_object& obj) + : cdef_meta_object (obj) + { + // This should never happen... + if (! is_package ()) + error ("internal error: invalid assignment from %s to meta.package object", + class_name ().c_str ()); + } + + cdef_package& operator = (const cdef_package& pack) + { + cdef_object::operator= (pack); + + return *this; + } + + void install_class (const cdef_class& cls, const std::string& nm) + { get_rep ()->install_class (cls, nm); } + + void install_function (const octave_value& fcn, const std::string& nm) + { get_rep ()->install_function (fcn, nm); } + + void install_package (const cdef_package& pack, const std::string& nm) + { get_rep ()->install_package (pack, nm); } + + Cell get_classes (void) const + { return get_rep ()->get_classes (); } + + Cell get_functions (void) const + { return get_rep ()->get_functions (); } + + Cell get_packages (void) const + { return get_rep ()->get_packages (); } + + std::string get_name (void) const { return get_rep ()->get_name (); } + + octave_value find (const std::string& nm) { return get_rep ()->find (nm); } + + static const cdef_package& meta (void) { return _meta; } + +private: + cdef_package_rep* get_rep (void) + { return dynamic_cast (cdef_object::get_rep ()); } + + const cdef_package_rep* get_rep (void) const + { return dynamic_cast (cdef_object::get_rep ()); } + +private: + static cdef_package _meta; + + friend void install_classdef (void); +}; + +class +octave_classdef : public octave_base_value +{ +public: + octave_classdef (void) + : octave_base_value (), object () { } + + octave_classdef (const cdef_object& obj) + : octave_base_value (), object (obj) { } + + octave_classdef (const octave_classdef& obj) + : octave_base_value (obj), object (obj.object) { } + + octave_base_value* clone (void) const + { return new octave_classdef (object.clone ()); } + + octave_base_value* empty_clone (void) const + { return new octave_classdef (object.empty_clone ()); } + + cdef_object get_object (void) const { return object; } + + cdef_object& get_object_ref (void) { return object; } + + bool is_defined (void) const { return true; } + + bool is_map (void) const { return true; } + + bool print_as_scalar (void) const { return true; } + + void print(std::ostream& os, bool pr_as_read_syntax = false) const + { + // FIXME: should call "display" method + print_raw(os, pr_as_read_syntax); + newline(os); + } + + void print_raw(std::ostream& os, bool /* pr_as_read_syntax */ = false) const + { + if (object.is_array ()) + os << "array (" << object.dims ().str () << ") of " + << object.class_name () << " objects"; + else + os << object.class_name () << " object"; + } + + octave_value_list subsref (const std::string& type, + const std::list& idx, int nargout); + + octave_value subsref (const std::string& type, + const std::list& idx) + { + octave_value_list retval = subsref (type, idx, 1); + return (retval.length () > 0 ? retval(0) : octave_value ()); + } + + octave_value subsref (const std::string& type, + const std::list& idx, + bool auto_add); + + octave_value subsasgn (const std::string& type, + const std::list& idx, + const octave_value& rhs); + + octave_value + undef_subsasgn (const std::string& type, + const std::list& idx, + const octave_value& rhs); + + string_vector map_keys (void) const { return object.map_keys (); } + + dim_vector dims (void) const { return object.dims (); } + +private: + cdef_object object; + +private: + DECLARE_OCTAVE_ALLOCATOR + +public: + int type_id (void) const { return t_id; } + std::string type_name (void) const { return t_name; } + std::string class_name (void) const { return object.class_name (); } + + static int static_type_id (void) { return t_id; } + static std::string static_type_name (void) { return t_name; } + static std::string static_class_name (void) { return ""; } + static void register_type (void); + +private: + static int t_id; + + static const std::string t_name; +}; + +inline octave_value +to_ov (const cdef_object& obj) +{ + if (obj.ok ()) + return octave_value (new octave_classdef (obj)); + else + return octave_value (Matrix ()); +} + +inline octave_value +to_ov (const octave_value& ov) +{ return ov; } + +inline cdef_object +to_cdef (const octave_value& val) +{ + if (val.type_name () == "object") + return dynamic_cast (val.internal_rep ())->get_object (); + else + { + warning ("trying to cast non-object into object"); + return cdef_object (); + } +} + +inline cdef_object& +to_cdef_ref (octave_value& val) +{ + static cdef_object empty; + + if (val.type_name () == "object") + return dynamic_cast (val.internal_rep ())->get_object_ref (); + else + { + warning ("trying to cast non-object into object"); + return empty; + } +} + +inline cdef_object +to_cdef (const cdef_object& obj) +{ return obj; } + +OCTINTERP_API void install_classdef (void); + +class +cdef_manager +{ +public: + + static cdef_class find_class (const std::string& name, + bool error_if_not_found = true, + bool load_if_not_found = true) + { + if (instance_ok ()) + return instance->do_find_class (name, error_if_not_found, + load_if_not_found); + + return cdef_class (); + } + + static octave_function* find_method_symbol (const std::string& method_name, + const std::string& class_name) + { + if (instance_ok ()) + return instance->do_find_method_symbol (method_name, class_name); + + return 0; + } + + static cdef_package find_package (const std::string& name, + bool error_if_not_found = true, + bool load_if_not_found = true) + { + if (instance_ok ()) + return instance->do_find_package (name, error_if_not_found, + load_if_not_found); + + return cdef_package (); + } + + static octave_function* find_package_symbol (const std::string& pack_name) + { + if (instance_ok ()) + return instance->do_find_package_symbol (pack_name); + + return 0; + } + + static void register_class (const cdef_class& cls) + { + if (instance_ok ()) + instance->do_register_class (cls); + } + + static void unregister_class (const cdef_class& cls) + { + if (instance_ok ()) + instance->do_unregister_class (cls); + } + + static void register_package (const cdef_package& pkg) + { + if (instance_ok ()) + instance->do_register_package (pkg); + } + + static void unregister_package (const cdef_package& pkg) + { + if (instance_ok ()) + instance->do_unregister_package (pkg); + } + +private: + + cdef_manager (void) { } + + cdef_manager (const cdef_manager&); + + cdef_manager& operator = (const cdef_manager&); + + ~cdef_manager (void) { } + + static void create_instance (void); + + static bool instance_ok (void) + { + bool retval = true; + + if (! instance) + create_instance (); + + if (! instance) + { + ::error ("unable to create cdef_manager!"); + + retval = false; + } + + return retval; + } + + static void cleanup_instance (void) + { + delete instance; + + instance = 0; + } + + cdef_class do_find_class (const std::string& name, bool error_if_not_found, + bool load_if_not_found); + + octave_function* do_find_method_symbol (const std::string& method_name, + const std::string& class_name); + + cdef_package do_find_package (const std::string& name, + bool error_if_not_found, + bool load_if_not_found); + + octave_function* do_find_package_symbol (const std::string& pack_name); + + void do_register_class (const cdef_class& cls) + { all_classes[cls.get_name ()] = cls; } + + void do_unregister_class (const cdef_class& cls) + { all_classes.erase(cls.get_name ()); } + + void do_register_package (const cdef_package& pkg) + { all_packages[pkg.get_name ()] = pkg; } + + void do_unregister_package (const cdef_package& pkg) + { all_packages.erase(pkg.get_name ()); } + +private: + + // The single cdef_manager instance + static cdef_manager *instance; + + // All registered/loaded classes + std::map all_classes; + + // All registered/loaded packages + std::map all_packages; +}; + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-complex.cc --- a/libinterp/octave-value/ov-complex.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-complex.cc Tue Jan 07 16:07:54 2014 -0500 @@ -315,7 +315,8 @@ bool /* save_as_floats */) { hsize_t dimens[3]; - hid_t space_hid = -1, type_hid = -1, data_hid = -1; + hid_t space_hid, type_hid, data_hid; + space_hid = type_hid = data_hid = -1; bool retval = true; space_hid = H5Screate_simple (0, dimens, 0); diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-cx-diag.cc --- a/libinterp/octave-value/ov-cx-diag.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-cx-diag.cc Tue Jan 07 16:07:54 2014 -0500 @@ -167,7 +167,8 @@ octave_complex_diag_matrix::save_binary (std::ostream& os, bool& save_as_floats) { - int32_t r = matrix.rows (), c = matrix.cols (); + int32_t r = matrix.rows (); + int32_t c = matrix.cols (); os.write (reinterpret_cast (&r), 4); os.write (reinterpret_cast (&c), 4); diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-cx-mat.cc --- a/libinterp/octave-value/ov-cx-mat.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-cx-mat.cc Tue Jan 07 16:07:54 2014 -0500 @@ -561,7 +561,8 @@ return (empty > 0); int rank = dv.length (); - hid_t space_hid = -1, data_hid = -1, type_hid = -1; + hid_t space_hid, data_hid, type_hid; + space_hid = data_hid = type_hid = -1; bool retval = true; ComplexNDArray m = complex_array_value (); diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-cx-sparse.cc --- a/libinterp/octave-value/ov-cx-sparse.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-cx-sparse.cc Tue Jan 07 16:07:54 2014 -0500 @@ -390,7 +390,8 @@ if (group_hid < 0) return false; - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid, data_hid; + space_hid = data_hid = -1; bool retval = true; SparseComplexMatrix m = sparse_complex_matrix_value (); octave_idx_type tmp; diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-fcn-handle.cc --- a/libinterp/octave-value/ov-fcn-handle.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-fcn-handle.cc Tue Jan 07 16:07:54 2014 -0500 @@ -270,7 +270,7 @@ std::string dir_name = str.substr (0, xpos); octave_function *xfcn - = load_fcn_from_file (str, dir_name, "", nm); + = load_fcn_from_file (str, dir_name, "", "", nm); if (xfcn) { @@ -300,7 +300,7 @@ std::string dir_name = str.substr (0, xpos); - octave_function *xfcn = load_fcn_from_file (str, dir_name, "", nm); + octave_function *xfcn = load_fcn_from_file (str, dir_name, "", "", nm); if (xfcn) { @@ -323,7 +323,7 @@ std::string dir_name = fpath.substr (0, xpos); - octave_function *xfcn = load_fcn_from_file (fpath, dir_name, "", nm); + octave_function *xfcn = load_fcn_from_file (fpath, dir_name, "", "", nm); if (xfcn) { @@ -721,7 +721,8 @@ if (group_hid < 0) return false; - hid_t space_hid = -1, data_hid = -1, type_hid = -1;; + hid_t space_hid, data_hid, type_hid; + space_hid = data_hid = type_hid = -1; // attach the type of the variable type_hid = H5Tcopy (H5T_C_S1); diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-fcn-inline.cc --- a/libinterp/octave-value/ov-fcn-inline.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-fcn-inline.cc Tue Jan 07 16:07:54 2014 -0500 @@ -291,7 +291,8 @@ if (len < ifargs(i).length ()) len = ifargs(i).length (); - hid_t space_hid = -1, data_hid = -1, type_hid = -1;; + hid_t space_hid, data_hid, type_hid; + space_hid = data_hid = type_hid = -1; bool retval = true; // FIXME: Is there a better way of saving string vectors, diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-fcn.h --- a/libinterp/octave-value/ov-fcn.h Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-fcn.h Tue Jan 07 16:07:54 2014 -0500 @@ -85,6 +85,10 @@ virtual bool is_class_constructor (const std::string& = std::string ()) const { return false; } + virtual bool + is_classdef_constructor (const std::string& = std::string ()) const + { return false; } + virtual bool is_class_method (const std::string& = std::string ()) const { return false; } @@ -160,6 +164,9 @@ virtual void accept (tree_walker&) { } + virtual bool is_postfix_index_handled (char type) const + { return (type == '(' || type == '{'); } + protected: octave_function (const std::string& nm, diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-float.cc --- a/libinterp/octave-value/ov-float.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-float.cc Tue Jan 07 16:07:54 2014 -0500 @@ -191,7 +191,8 @@ bool /* save_as_floats */) { hsize_t dimens[3]; - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid, data_hid; + space_hid = data_hid = -1; bool retval = true; space_hid = H5Screate_simple (0, dimens, 0); @@ -326,8 +327,31 @@ SCALAR_MAPPER (isnan, xisnan); SCALAR_MAPPER (xsignbit, xsignbit); + // Special cases for Matlab compatibility. + case umap_xtolower: + case umap_xtoupper: + return scalar; + + case umap_xisalnum: + case umap_xisalpha: + case umap_xisascii: + case umap_xiscntrl: + case umap_xisdigit: + case umap_xisgraph: + case umap_xislower: + case umap_xisprint: + case umap_xispunct: + case umap_xisspace: + case umap_xisupper: + case umap_xisxdigit: + case umap_xtoascii: + { + octave_value str_conv = convert_to_str (true, true); + return error_state ? octave_value () : str_conv.map (umap); + } + default: - return octave_base_value::map (umap); + return octave_base_value::map (umap); } } diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-flt-complex.cc --- a/libinterp/octave-value/ov-flt-complex.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-flt-complex.cc Tue Jan 07 16:07:54 2014 -0500 @@ -300,7 +300,8 @@ bool /* save_as_floats */) { hsize_t dimens[3]; - hid_t space_hid = -1, type_hid = -1, data_hid = -1; + hid_t space_hid, type_hid, data_hid; + space_hid = type_hid = data_hid = -1; bool retval = true; space_hid = H5Screate_simple (0, dimens, 0); diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-flt-cx-diag.cc --- a/libinterp/octave-value/ov-flt-cx-diag.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-flt-cx-diag.cc Tue Jan 07 16:07:54 2014 -0500 @@ -150,7 +150,8 @@ bool& /* save_as_floats */) { - int32_t r = matrix.rows (), c = matrix.cols (); + int32_t r = matrix.rows (); + int32_t c = matrix.cols (); os.write (reinterpret_cast (&r), 4); os.write (reinterpret_cast (&c), 4); diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-flt-cx-mat.cc --- a/libinterp/octave-value/ov-flt-cx-mat.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-flt-cx-mat.cc Tue Jan 07 16:07:54 2014 -0500 @@ -536,7 +536,8 @@ return (empty > 0); int rank = dv.length (); - hid_t space_hid = -1, data_hid = -1, type_hid = -1; + hid_t space_hid, data_hid, type_hid; + space_hid = data_hid = type_hid = -1; bool retval = true; FloatComplexNDArray m = complex_array_value (); diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-flt-re-diag.cc --- a/libinterp/octave-value/ov-flt-re-diag.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-flt-re-diag.cc Tue Jan 07 16:07:54 2014 -0500 @@ -119,7 +119,8 @@ bool& /* save_as_floats*/) { - int32_t r = matrix.rows (), c = matrix.cols (); + int32_t r = matrix.rows (); + int32_t c = matrix.cols (); os.write (reinterpret_cast (&r), 4); os.write (reinterpret_cast (&c), 4); diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-flt-re-mat.cc --- a/libinterp/octave-value/ov-flt-re-mat.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-flt-re-mat.cc Tue Jan 07 16:07:54 2014 -0500 @@ -563,7 +563,8 @@ return (empty > 0); int rank = dv.length (); - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid, data_hid; + space_hid = data_hid = -1; bool retval = true; FloatNDArray m = array_value (); @@ -811,6 +812,29 @@ ARRAY_MAPPER (isna, bool, octave_is_NA); ARRAY_MAPPER (xsignbit, float, xsignbit); + // Special cases for Matlab compatibility. + case umap_xtolower: + case umap_xtoupper: + return matrix; + + case umap_xisalnum: + case umap_xisalpha: + case umap_xisascii: + case umap_xiscntrl: + case umap_xisdigit: + case umap_xisgraph: + case umap_xislower: + case umap_xisprint: + case umap_xispunct: + case umap_xisspace: + case umap_xisupper: + case umap_xisxdigit: + case umap_xtoascii: + { + octave_value str_conv = convert_to_str (true, true); + return error_state ? octave_value () : str_conv.map (umap); + } + default: return octave_base_value::map (umap); } diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-intx.h --- a/libinterp/octave-value/ov-intx.h Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-intx.h Tue Jan 07 16:07:54 2014 -0500 @@ -358,8 +358,15 @@ case umap_finite: return boolNDArray (matrix.dims (), true); + // Special cases for Matlab compatibility. + case umap_xtolower: + case umap_xtoupper: + return matrix; + default: { + // FIXME: we should be able to do better than converting to + // double here. octave_matrix m (array_value ()); return m.map (umap); } @@ -658,6 +665,11 @@ case umap_finite: return true; + // Special cases for Matlab compatibility. + case umap_xtolower: + case umap_xtoupper: + return scalar; + default: { octave_scalar m (scalar_value ()); diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-java.cc --- a/libinterp/octave-value/ov-java.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-java.cc Tue Jan 07 16:07:54 2014 -0500 @@ -1150,7 +1150,8 @@ if (jni_env->IsInstanceOf (jobj, cls)) { jobjectArray jarr = reinterpret_cast (jobj); - int rows = jni_env->GetArrayLength (jarr), cols = 0; + int rows = jni_env->GetArrayLength (jarr); + int cols = 0; if (rows > 0) { diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-range.cc --- a/libinterp/octave-value/ov-range.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-range.cc Tue Jan 07 16:07:54 2014 -0500 @@ -549,7 +549,8 @@ bool /* save_as_floats */) { hsize_t dimens[3]; - hid_t space_hid = -1, type_hid = -1, data_hid = -1; + hid_t space_hid, type_hid, data_hid; + space_hid = type_hid = data_hid = -1; bool retval = true; space_hid = H5Screate_simple (0, dimens, 0); diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-re-diag.cc --- a/libinterp/octave-value/ov-re-diag.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-re-diag.cc Tue Jan 07 16:07:54 2014 -0500 @@ -179,7 +179,8 @@ octave_diag_matrix::save_binary (std::ostream& os, bool& save_as_floats) { - int32_t r = matrix.rows (), c = matrix.cols (); + int32_t r = matrix.rows (); + int32_t c = matrix.cols (); os.write (reinterpret_cast (&r), 4); os.write (reinterpret_cast (&c), 4); diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-re-mat.cc --- a/libinterp/octave-value/ov-re-mat.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-re-mat.cc Tue Jan 07 16:07:54 2014 -0500 @@ -675,7 +675,8 @@ return (empty > 0); int rank = dv.length (); - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid, data_hid; + space_hid = data_hid = -1; bool retval = true; NDArray m = array_value (); @@ -934,13 +935,30 @@ ARRAY_MAPPER (isna, bool, octave_is_NA); ARRAY_MAPPER (xsignbit, double, xsignbit); + // Special cases for Matlab compatibility. + case umap_xtolower: + case umap_xtoupper: + return matrix; + + case umap_xisalnum: + case umap_xisalpha: + case umap_xisascii: + case umap_xiscntrl: + case umap_xisdigit: + case umap_xisgraph: + case umap_xislower: + case umap_xisprint: + case umap_xispunct: + case umap_xisspace: + case umap_xisupper: + case umap_xisxdigit: + case umap_xtoascii: + { + octave_value str_conv = convert_to_str (true, true); + return error_state ? octave_value () : str_conv.map (umap); + } + default: - if (umap >= umap_xisalnum && umap <= umap_xtoupper) - { - octave_value str_conv = convert_to_str (true, true); - return error_state ? octave_value () : str_conv.map (umap); - } - else return octave_base_value::map (umap); } } diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-re-sparse.cc --- a/libinterp/octave-value/ov-re-sparse.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-re-sparse.cc Tue Jan 07 16:07:54 2014 -0500 @@ -421,7 +421,8 @@ if (group_hid < 0) return false; - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid, data_hid; + space_hid = data_hid = -1; bool retval = true; SparseMatrix m = sparse_matrix_value (); octave_idx_type tmp; diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-scalar.cc --- a/libinterp/octave-value/ov-scalar.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-scalar.cc Tue Jan 07 16:07:54 2014 -0500 @@ -206,7 +206,8 @@ bool /* save_as_floats */) { hsize_t dimens[3]; - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid, data_hid; + space_hid = data_hid = -1; bool retval = true; space_hid = H5Screate_simple (0, dimens, 0); @@ -342,14 +343,31 @@ SCALAR_MAPPER (isnan, xisnan); SCALAR_MAPPER (xsignbit, xsignbit); + // Special cases for Matlab compatibility. + case umap_xtolower: + case umap_xtoupper: + return scalar; + + case umap_xisalnum: + case umap_xisalpha: + case umap_xisascii: + case umap_xiscntrl: + case umap_xisdigit: + case umap_xisgraph: + case umap_xislower: + case umap_xisprint: + case umap_xispunct: + case umap_xisspace: + case umap_xisupper: + case umap_xisxdigit: + case umap_xtoascii: + { + octave_value str_conv = convert_to_str (true, true); + return error_state ? octave_value () : str_conv.map (umap); + } + default: - if (umap >= umap_xisalnum && umap <= umap_xtoupper) - { - octave_value str_conv = convert_to_str (true, true); - return error_state ? octave_value () : str_conv.map (umap); - } - else - return octave_base_value::map (umap); + return octave_base_value::map (umap); } } diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-str-mat.cc --- a/libinterp/octave-value/ov-str-mat.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-str-mat.cc Tue Jan 07 16:07:54 2014 -0500 @@ -583,7 +583,8 @@ return (empty > 0); int rank = dv.length (); - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid, data_hid; + space_hid = data_hid = -1; bool retval = true; charNDArray m = char_array_value (); diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-usr-fcn.cc --- a/libinterp/octave-value/ov-usr-fcn.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-usr-fcn.cc Tue Jan 07 16:07:54 2014 -0500 @@ -203,7 +203,7 @@ num_named_args (param_list ? param_list->length () : 0), subfunction (false), inline_function (false), anonymous_function (false), nested_function (false), - class_constructor (false), class_method (false), + class_constructor (none), class_method (false), parent_scope (-1), local_scope (sid), curr_unwind_protect_frame (0) #ifdef HAVE_LLVM @@ -470,7 +470,7 @@ octave_value_list octave_user_function::do_multi_index_op (int nargout, - const octave_value_list& args, + const octave_value_list& _args, const std::list* lvalue_list) { octave_value_list retval; @@ -481,6 +481,23 @@ if (! cmd_list) return retval; + // If this function is a classdef constructor, extract the first input + // argument, which must be the partially constructed object instance. + + octave_value_list args (_args); + octave_value_list ret_args; + + if (is_classdef_constructor ()) + { + if (args.length () > 0) + { + ret_args = args.slice (0, 1, true); + args = args.slice (1, args.length () - 1, true); + } + else + panic_impossible (); + } + #ifdef HAVE_LLVM if (is_special_expr () && tree_jit::execute (*this, args, retval)) @@ -524,6 +541,25 @@ return retval; } + // For classdef constructor, pre-populate the output arguments + // with the pre-initialized object instance, extracted above. + + if (is_classdef_constructor ()) + { + if (ret_list) + { + ret_list->define_from_arg_vector (ret_args); + if (error_state) + return retval; + } + else + { + ::error ("%s: invalid classdef constructor, no output argument defined", + dispatch_class ().c_str ()); + return retval; + } + } + // Force parameter list to be undefined when this function exits. // Doing so decrements the reference counts on the values of local // variables that are also named function parameters. @@ -743,7 +779,8 @@ { // Only assign the hidden variable if black holes actually present. Matrix bh (1, nbh); - octave_idx_type k = 0, l = 0; + octave_idx_type k = 0; + octave_idx_type l = 0; for (std::list::const_iterator p = lvalue_list->begin (); p != lvalue_list->end (); p++) { diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov-usr-fcn.h --- a/libinterp/octave-value/ov-usr-fcn.h Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov-usr-fcn.h Tue Jan 07 16:07:54 2014 -0500 @@ -327,12 +327,20 @@ void mark_as_nested_function (void) { nested_function = true; } - void mark_as_class_constructor (void) { class_constructor = true; } + void mark_as_class_constructor (void) { class_constructor = legacy; } + + void mark_as_classdef_constructor (void) { class_constructor = classdef; } bool is_class_constructor (const std::string& cname = std::string ()) const { - return class_constructor - ? (cname.empty () ? true : cname == dispatch_class ()) : false; + return class_constructor == legacy + ? (cname.empty () ? true : cname == dispatch_class ()) : false; + } + + bool is_classdef_constructor (const std::string& cname = std::string ()) const + { + return class_constructor == classdef + ? (cname.empty () ? true : cname == dispatch_class ()) : false; } void mark_as_class_method (void) { class_method = true; } @@ -408,6 +416,13 @@ private: + enum class_ctor_type + { + none, + legacy, + classdef + }; + // List of arguments for this function. These are local variables. tree_parameter_list *param_list; @@ -470,8 +485,8 @@ // TRUE means this is a nested function. (either a child or parent) bool nested_function; - // TRUE means this function is the constructor for class object. - bool class_constructor; + // Enum describing whether this function is the constructor for class object. + class_ctor_type class_constructor; // TRUE means this function is a method for a class. bool class_method; diff -r e42d4f152766 -r 8f256148d82b libinterp/octave-value/ov.cc --- a/libinterp/octave-value/ov.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave-value/ov.cc Tue Jan 07 16:07:54 2014 -0500 @@ -65,6 +65,7 @@ #include "ov-range.h" #include "ov-struct.h" #include "ov-class.h" +#include "ov-classdef.h" #include "ov-oncleanup.h" #include "ov-cs-list.h" #include "ov-colon.h" diff -r e42d4f152766 -r 8f256148d82b libinterp/octave.cc --- a/libinterp/octave.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/octave.cc Tue Jan 07 16:07:54 2014 -0500 @@ -68,6 +68,7 @@ #include "ops.h" #include "options-usage.h" #include "ov.h" +#include "ov-classdef.h" #include "ov-range.h" #include "toplev.h" #include "parse.h" @@ -754,6 +755,8 @@ install_builtins (); + install_classdef (); + for (std::list::const_iterator it = command_line_path.begin (); it != command_line_path.end (); it++) load_path::set_command_line_path (*it); diff -r e42d4f152766 -r 8f256148d82b libinterp/operators/op-b-b.cc --- a/libinterp/operators/op-b-b.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/operators/op-b-b.cc Tue Jan 07 16:07:54 2014 -0500 @@ -33,6 +33,7 @@ #include "ov-float.h" #include "ov-re-mat.h" #include "ov-typeinfo.h" +#include "ov-null-mat.h" #include "ops.h" #include "xdiv.h" #include "xpow.h" @@ -92,4 +93,8 @@ INSTALL_CATOP (octave_float_scalar, octave_bool, f_b); INSTALL_ASSIGNCONV (octave_bool, octave_bool, octave_bool_matrix); + + INSTALL_ASSIGNCONV (octave_bool, octave_null_matrix, octave_bool_matrix); + INSTALL_ASSIGNCONV (octave_bool, octave_null_str, octave_bool_matrix); + INSTALL_ASSIGNCONV (octave_bool, octave_null_sq_str, octave_bool_matrix); } diff -r e42d4f152766 -r 8f256148d82b libinterp/operators/op-int.h --- a/libinterp/operators/op-int.h Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/operators/op-int.h Tue Jan 07 16:07:54 2014 -0500 @@ -1160,7 +1160,10 @@ #define OCTAVE_INSTALL_INT_NULL_ASSIGN_OPS(TYPE) \ INSTALL_ASSIGNOP (op_asn_eq, octave_ ## TYPE ## _matrix, octave_null_matrix, TYPE ## null_assign) \ INSTALL_ASSIGNOP (op_asn_eq, octave_ ## TYPE ## _matrix, octave_null_str, TYPE ## null_assign) \ - INSTALL_ASSIGNOP (op_asn_eq, octave_ ## TYPE ## _matrix, octave_null_sq_str, TYPE ## null_assign) + INSTALL_ASSIGNOP (op_asn_eq, octave_ ## TYPE ## _matrix, octave_null_sq_str, TYPE ## null_assign) \ + INSTALL_ASSIGNCONV (octave_ ## TYPE ## _scalar, octave_null_matrix, octave_ ## TYPE ## _matrix) \ + INSTALL_ASSIGNCONV (octave_## TYPE ## _scalar, octave_null_str, octave_ ## TYPE ## _matrix) \ + INSTALL_ASSIGNCONV (octave_## TYPE ## _scalar, octave_null_sq_str, octave_ ## TYPE ## _matrix) #define OCTAVE_INSTALL_INT_OPS(TYPE) \ OCTAVE_INSTALL_SS_INT_OPS (TYPE) \ diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/lex.h --- a/libinterp/parse-tree/lex.h Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/parse-tree/lex.h Tue Jan 07 16:07:54 2014 -0500 @@ -261,7 +261,9 @@ looking_at_matrix_or_assign_lhs (false), looking_for_object_index (false), looking_at_indirect_ref (false), parsing_class_method (false), - maybe_classdef_get_set_method (false), parsing_classdef (false), + parsing_classdef (false), maybe_classdef_get_set_method (false), + parsing_classdef_get_method (false), + parsing_classdef_set_method (false), quote_is_transpose (false), force_script (false), reading_fcn_file (false), reading_script_file (false), reading_classdef_file (false), @@ -341,13 +343,19 @@ // true means we are parsing a class method in function or classdef file. bool parsing_class_method; + // true means we are parsing a classdef file + bool parsing_classdef; + // true means we are parsing a class method declaration line in a // classdef file and can accept a property get or set method name. // for example, "get.propertyname" is recognized as a function name. bool maybe_classdef_get_set_method; - // true means we are parsing a classdef file - bool parsing_classdef; + // TRUE means we are parsing a classdef get.method. + bool parsing_classdef_get_method; + + // TRUE means we are parsing a classdef set.method. + bool parsing_classdef_set_method; // return transpose or start a string? bool quote_is_transpose; diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/lex.ll --- a/libinterp/parse-tree/lex.ll Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/parse-tree/lex.ll Tue Jan 07 16:07:54 2014 -0500 @@ -1169,7 +1169,7 @@ { curr_lexer->looking_for_object_index = true; - return curr_lexer->count_token_internal (SUPERCLASSREF); + return curr_lexer->count_token_internal (id_tok); } } } @@ -1196,7 +1196,7 @@ { curr_lexer->looking_for_object_index = true; - return curr_lexer->count_token_internal (METAQUERY); + return curr_lexer->count_token_internal (id_tok); } } } @@ -1926,8 +1926,10 @@ looking_for_object_index = false; looking_at_indirect_ref = false; parsing_class_method = false; + parsing_classdef = false; maybe_classdef_get_set_method = false; - parsing_classdef = false; + parsing_classdef_get_method = false; + parsing_classdef_set_method = false; force_script = false; reading_fcn_file = false; reading_script_file = false; @@ -2327,20 +2329,6 @@ at_beginning_of_statement = true; break; - case static_kw: - if ((reading_fcn_file || reading_script_file - || reading_classdef_file) - && ! fcn_file_full_name.empty ()) - warning_with_id ("Octave:deprecated-keyword", - "the 'static' keyword is obsolete and will be removed from a future version of Octave; please use 'persistent' instead; near line %d of file '%s'", - input_line_number, - fcn_file_full_name.c_str ()); - else - warning_with_id ("Octave:deprecated-keyword", - "the 'static' keyword is obsolete and will be removed from a future version of Octave; please use 'persistent' instead; near line %d", - input_line_number); - // fall through ... - case persistent_kw: case global_kw: looking_at_decl_list = true; @@ -2696,36 +2684,30 @@ int octave_base_lexer::handle_superclass_identifier (void) { - std::string pkg; - char *yytxt = flex_yytext (); - std::string meth = strip_trailing_whitespace (yytxt); + std::string meth = flex_yytext (); + size_t pos = meth.find ("@"); - std::string cls = meth.substr (pos).substr (1); - meth = meth.substr (0, pos - 1); - + std::string cls = meth.substr (pos + 1); + meth = meth.substr (0, pos); + + std::string pkg; pos = cls.find ("."); if (pos != std::string::npos) { - pkg = cls.substr (pos).substr (1); - cls = cls.substr (0, pos - 1); + pkg = cls.substr (0, pos); + cls = cls.substr (pos + 1); } int kw_token = (is_keyword_token (meth) || is_keyword_token (cls) || is_keyword_token (pkg)); if (kw_token) { - error ("method, class and package names may not be keywords"); + error ("method, class, and package names may not be keywords"); return LEXICAL_ERROR; } - symbol_table::scope_id sid = symtab_context.curr_scope (); - - push_token (new token - (SUPERCLASSREF, - meth.empty () ? 0 : &(symbol_table::insert (meth, sid)), - cls.empty () ? 0 : &(symbol_table::insert (cls, sid)), - pkg.empty () ? 0 : &(symbol_table::insert (pkg, sid)), - input_line_number, current_input_column)); + push_token (new token (SUPERCLASSREF, meth, pkg, cls, + input_line_number, current_input_column)); current_input_column += flex_yyleng (); @@ -2735,31 +2717,25 @@ int octave_base_lexer::handle_meta_identifier (void) { + std::string cls = std::string(flex_yytext ()).substr (1); + std::string pkg; - char *yytxt = flex_yytext (); - std::string cls = strip_trailing_whitespace (yytxt).substr (1); size_t pos = cls.find ("."); - if (pos != std::string::npos) { - pkg = cls.substr (pos).substr (1); - cls = cls.substr (0, pos - 1); + pkg = cls.substr (0, pos); + cls = cls.substr (pos + 1); } int kw_token = is_keyword_token (cls) || is_keyword_token (pkg); if (kw_token) { - error ("class and package names may not be keywords"); + error ("class and package names may not be keywords"); return LEXICAL_ERROR; } - symbol_table::scope_id sid = symtab_context.curr_scope (); - - push_token (new token - (METAQUERY, - cls.empty () ? 0 : &(symbol_table::insert (cls, sid)), - pkg.empty () ? 0 : &(symbol_table::insert (pkg, sid)), - input_line_number, current_input_column)); + push_token (new token (METAQUERY, pkg, cls, input_line_number, + current_input_column)); current_input_column += flex_yyleng (); diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/module.mk --- a/libinterp/parse-tree/module.mk Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/parse-tree/module.mk Tue Jan 07 16:07:54 2014 -0500 @@ -21,6 +21,7 @@ parse-tree/pt-cbinop.h \ parse-tree/pt-cell.h \ parse-tree/pt-check.h \ + parse-tree/pt-classdef.h \ parse-tree/pt-cmd.h \ parse-tree/pt-colon.h \ parse-tree/pt-const.h \ @@ -29,6 +30,7 @@ parse-tree/pt-except.h \ parse-tree/pt-exp.h \ parse-tree/pt-fcn-handle.h \ + parse-tree/pt-funcall.h \ parse-tree/pt-id.h \ parse-tree/pt-idx.h \ parse-tree/pt-jump.h \ @@ -52,6 +54,7 @@ parse-tree/pt-cbinop.cc \ parse-tree/pt-cell.cc \ parse-tree/pt-check.cc \ + parse-tree/pt-classdef.cc \ parse-tree/pt-cmd.cc \ parse-tree/pt-colon.cc \ parse-tree/pt-const.cc \ @@ -60,6 +63,7 @@ parse-tree/pt-except.cc \ parse-tree/pt-exp.cc \ parse-tree/pt-fcn-handle.cc \ + parse-tree/pt-funcall.cc \ parse-tree/pt-id.cc \ parse-tree/pt-idx.cc \ parse-tree/pt-jump.cc \ diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/oct-parse.in.yy --- a/libinterp/parse-tree/oct-parse.in.yy Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/parse-tree/oct-parse.in.yy Tue Jan 07 16:07:54 2014 -0500 @@ -62,6 +62,7 @@ #include "load-path.h" #include "oct-hist.h" #include "oct-map.h" +#include "ov-classdef.h" #include "ov-fcn-handle.h" #include "ov-usr-fcn.h" #include "ov-null-mat.h" @@ -70,6 +71,7 @@ #include "parse.h" #include "pt-all.h" #include "pt-eval.h" +#include "pt-funcall.h" #include "symtab.h" #include "token.h" #include "unwind-prot.h" @@ -164,6 +166,8 @@ tree_expression *tree_expression_type; tree_constant *tree_constant_type; tree_fcn_handle *tree_fcn_handle_type; + tree_funcall *tree_funcall_type; + tree_function_def *tree_function_def_type; tree_anon_fcn_handle *tree_anon_fcn_handle_type; tree_identifier *tree_identifier_type; tree_index_expression *tree_index_expression_type; @@ -183,7 +187,24 @@ tree_statement *tree_statement_type; tree_statement_list *tree_statement_list_type; octave_user_function *octave_user_function_type; - void *dummy_type; + + tree_classdef *tree_classdef_type; + tree_classdef_attribute* tree_classdef_attribute_type; + tree_classdef_attribute_list* tree_classdef_attribute_list_type; + tree_classdef_superclass* tree_classdef_superclass_type; + tree_classdef_superclass_list* tree_classdef_superclass_list_type; + tree_classdef_body* tree_classdef_body_type; + tree_classdef_property* tree_classdef_property_type; + tree_classdef_property_list* tree_classdef_property_list_type; + tree_classdef_properties_block* tree_classdef_properties_block_type; + tree_classdef_methods_list* tree_classdef_methods_list_type; + tree_classdef_methods_block* tree_classdef_methods_block_type; + tree_classdef_event* tree_classdef_event_type; + tree_classdef_events_list* tree_classdef_events_list_type; + tree_classdef_events_block* tree_classdef_events_block_type; + tree_classdef_enum* tree_classdef_enum_type; + tree_classdef_enum_list* tree_classdef_enum_list_type; + tree_classdef_enum_block* tree_classdef_enum_block_type; } // Tokens with line and column information. @@ -210,6 +231,7 @@ %token TRY CATCH %token GLOBAL PERSISTENT %token FCN_HANDLE +%token CLASSDEF %token PROPERTIES METHODS EVENTS ENUMERATION %token METAQUERY %token SUPERCLASSREF @@ -218,13 +240,12 @@ // Other tokens. %token END_OF_INPUT LEXICAL_ERROR -%token INPUT_FILE CLASSDEF +%token INPUT_FILE // %token VARARGIN VARARGOUT // Nonterminals we construct. -%type function_beg -%type stash_comment classdef_beg -%type properties_beg methods_beg events_beg enum_beg +%type stash_comment +%type function_beg classdef_beg %type sep_no_nl opt_sep_no_nl nl opt_nl sep opt_sep %type input %type string constant magic_colon @@ -236,18 +257,19 @@ %type primary_expr oper_expr power_expr %type simple_expr colon_expr assign_expr expression %type identifier fcn_name magic_tilde -%type superclass_identifier meta_identifier -%type function1 function2 classdef1 +%type superclass_identifier meta_identifier +%type function1 function2 %type word_list_cmd %type colon_expr1 %type arg_list word_list assign_lhs %type cell_or_matrix_row %type param_list param_list1 param_list2 %type return_list return_list1 -%type superclasses opt_superclasses %type command select_command loop_command -%type jump_command except_command function -%type file classdef +%type jump_command except_command +%type function +%type classdef +%type file %type if_command %type elseif_clause else_clause %type if_cmd_list1 if_cmd_list @@ -257,25 +279,25 @@ %type decl2 param_list_elt %type decl1 %type declaration -%type statement function_end classdef_end +%type statement function_end %type simple_list simple_list1 list list1 %type opt_list -// These types need to be specified. -%type attr -%type class_event -%type class_enum -%type class_property -%type properties_list -%type properties_block -%type methods_list -%type methods_block -%type opt_attr_list -%type attr_list -%type events_list -%type events_block -%type enum_list -%type enum_block -%type class_body +%type attr +%type attr_list opt_attr_list +%type superclass +%type superclass_list opt_superclass_list +%type class_body +%type class_property +%type property_list +%type properties_block +%type methods_list +%type methods_block +%type class_event +%type events_list +%type events_block +%type class_enum +%type enum_list +%type enum_block // Precedence and associativity. %right '=' ADD_EQ SUB_EQ MUL_EQ DIV_EQ LEFTDIV_EQ POW_EQ EMUL_EQ EDIV_EQ ELEFTDIV_EQ EPOW_EQ OR_EQ AND_EQ LSHIFT_EQ RSHIFT_EQ @@ -439,11 +461,26 @@ superclass_identifier : SUPERCLASSREF - { $$ = new tree_identifier ($1->line (), $1->column ()); } + { + std::string method_nm = $1->superclass_method_name (); + std::string package_nm = $1->superclass_package_name (); + std::string class_nm = $1->superclass_class_name (); + + $$ = parser.make_superclass_ref + (method_nm, package_nm, class_nm, + $1->line (), $1->column ()); + } ; meta_identifier : METAQUERY - { $$ = new tree_identifier ($1->line (), $1->column ()); } + { + std::string package_nm = $1->meta_package_name (); + std::string class_nm = $1->meta_class_name (); + + $$ = parser.make_meta_class_query + (package_nm, class_nm, + $1->line (), $1->column ()); + } ; string : DQ_STRING @@ -867,8 +904,6 @@ { $$ = $1; } | file { $$ = $1; } - | classdef - { $$ = $1; } ; // ===================== @@ -1294,6 +1329,13 @@ $$ = 0; } + | INPUT_FILE opt_nl classdef opt_sep END_OF_INPUT + { + if (lexer.reading_classdef_file) + parser.classdef_object = $3; + + $$ = 0; + } ; // =================== @@ -1336,12 +1378,14 @@ { lexer.parsed_function_name.top () = true; lexer.maybe_classdef_get_set_method = false; + lexer.parsing_classdef_get_method = true; $$ = $3; } | SET '.' identifier { lexer.parsed_function_name.top () = true; lexer.maybe_classdef_get_set_method = false; + lexer.parsing_classdef_set_method = true; $$ = $3; } ; @@ -1352,6 +1396,11 @@ delete $1; + if (lexer.parsing_classdef_get_method) + fname.insert (0, "get."); + else if (lexer.parsing_classdef_set_method) + fname.insert (0, "set."); + $$ = parser.frob_function (fname, $2); } ; @@ -1411,158 +1460,217 @@ // Classdef // ======== -classdef_beg : CLASSDEF stash_comment +classdef_beg : CLASSDEF { - $$ = 0; + if (! lexer.reading_classdef_file) + { + parser.bison_error ("classdef must appear inside a file containing only a class definition"); + YYABORT; + } + lexer.parsing_classdef = true; + $$ = $1; } ; -classdef_end : END +classdef : classdef_beg stash_comment opt_attr_list identifier opt_superclass_list opt_sep class_body opt_sep END { lexer.parsing_classdef = false; - if (parser.end_token_ok ($1, token::classdef_end)) - $$ = parser.make_end ("endclassdef", false, - $1->line (), $1->column ()); - else - ABORT_PARSE; + if (! ($$ = parser.make_classdef ($1, $3, $4, $5, $7, $9, $2))) + { + // make_classdef deleted $3, $4, $5, and $7. + ABORT_PARSE; + } } ; -classdef1 : classdef_beg opt_attr_list identifier opt_superclasses - { $$ = 0; } - ; - -classdef : classdef1 opt_sep class_body opt_sep stash_comment classdef_end - { $$ = 0; } - ; - opt_attr_list : // empty { $$ = 0; } | '(' attr_list ')' - { $$ = 0; } + { $$ = $2; } ; attr_list : attr - { $$ = 0; } + { $$ = new tree_classdef_attribute_list ($1); } | attr_list ',' attr - { $$ = 0; } + { + $1->append ($3); + $$ = $1; + } ; attr : identifier - { $$ = 0; } + { $$ = new tree_classdef_attribute ($1); } | identifier '=' decl_param_init expression - { $$ = 0; } + { + lexer.looking_at_initializer_expression = false; + $$ = new tree_classdef_attribute ($1, $4); + } | EXPR_NOT identifier - { $$ = 0; } + { $$ = new tree_classdef_attribute ($2, false); } ; -opt_superclasses +opt_superclass_list : // empty { $$ = 0; } - | superclasses - { $$ = 0; } + | superclass_list + { $$ = $1; } ; -superclasses : EXPR_LT identifier '.' identifier - { $$ = 0; } - | EXPR_LT identifier - { $$ = 0; } - | superclasses EXPR_AND identifier '.' identifier - { $$ = 0; } - | superclasses EXPR_AND identifier - { $$ = 0; } +superclass_list : EXPR_LT superclass + { $$ = new tree_classdef_superclass_list ($2); } + | superclass_list EXPR_AND superclass + { + $1->append ($3); + $$ = $1; + } + ; + +superclass : identifier + { $$ = new tree_classdef_superclass ($1); } + | identifier '.' identifier + { $$ = new tree_classdef_superclass ($3, $1); } ; class_body : properties_block - { $$ = 0; } + { $$ = new tree_classdef_body ($1); } | methods_block - { $$ = 0; } + { $$ = new tree_classdef_body ($1); } | events_block - { $$ = 0; } + { $$ = new tree_classdef_body ($1); } | enum_block - { $$ = 0; } + { $$ = new tree_classdef_body ($1); } | class_body opt_sep properties_block - { $$ = 0; } + { + $1->append ($3); + $$ = $1; + } | class_body opt_sep methods_block - { $$ = 0; } + { + $1->append ($3); + $$ = $1; + } | class_body opt_sep events_block - { $$ = 0; } + { + $1->append ($3); + $$ = $1; + } | class_body opt_sep enum_block - { $$ = 0; } - ; - -properties_beg : PROPERTIES stash_comment - { $$ = 0; } + { + $1->append ($3); + $$ = $1; + } ; properties_block - : properties_beg opt_attr_list opt_sep properties_list opt_sep END - { $$ = 0; } + : PROPERTIES stash_comment opt_attr_list opt_sep property_list opt_sep END + { + if (! ($$ = parser.make_classdef_properties_block + ($1, $3, $5, $7, $2))) + { + // make_classdef_properties_block delete $3 and $5. + ABORT_PARSE; + } + } ; -properties_list +property_list : class_property - { $$ = 0; } - | properties_list opt_sep class_property - { $$ = 0; } + { $$ = new tree_classdef_property_list ($1); } + | property_list opt_sep class_property + { + $1->append ($3); + $$ = $1; + } ; class_property : identifier - { $$ = 0; } + { $$ = new tree_classdef_property ($1); } | identifier '=' decl_param_init expression ';' - { $$ = 0; } + { + lexer.looking_at_initializer_expression = false; + $$ = new tree_classdef_property ($1, $4); + } ; -methods_beg : METHODS stash_comment - { $$ = 0; } - ; - -methods_block : methods_beg opt_attr_list opt_sep methods_list opt_sep END - { $$ = 0; } +methods_block : METHODS stash_comment opt_attr_list opt_sep methods_list opt_sep END + { + if (! ($$ = parser.make_classdef_methods_block + ($1, $3, $5, $7, $2))) + { + // make_classdef_methods_block deleted $3 and $5. + ABORT_PARSE; + } + } ; methods_list : function - { $$ = 0; } + { + octave_value fcn; + if ($1) + fcn = $1->function (); + delete $1; + $$ = new tree_classdef_methods_list (fcn); + } | methods_list opt_sep function - { $$ = 0; } + { + octave_value fcn; + if ($3) + fcn = $3->function (); + delete $3; + + $1->append (fcn); + $$ = $1; + } ; -events_beg : EVENTS stash_comment - { $$ = 0; } - ; - -events_block : events_beg opt_attr_list opt_sep events_list opt_sep END - { $$ = 0; } +events_block : EVENTS stash_comment opt_attr_list opt_sep events_list opt_sep END + { + if (! ($$ = parser.make_classdef_events_block + ($1, $3, $5, $7, $2))) + { + // make_classdef_events_block deleted $3 and $5. + ABORT_PARSE; + } + } ; events_list : class_event - { $$ = 0; } + { $$ = new tree_classdef_events_list ($1); } | events_list opt_sep class_event - { $$ = 0; } + { + $1->append ($3); + $$ = $1; + } ; class_event : identifier - { $$ = 0; } + { $$ = new tree_classdef_event ($1); } ; -enum_beg : ENUMERATION stash_comment - { $$ = 0; } - ; - -enum_block : enum_beg opt_attr_list opt_sep enum_list opt_sep END - { $$ = 0; } +enum_block : ENUMERATION stash_comment opt_attr_list opt_sep enum_list opt_sep END + { + if (! ($$ = parser.make_classdef_enum_block + ($1, $3, $5, $7, $2))) + { + // make_classdef_enum_block deleted $3 and $5. + ABORT_PARSE; + } + } ; enum_list : class_enum - { $$ = 0; } + { $$ = new tree_classdef_enum_list ($1); } | enum_list opt_sep class_enum - { $$ = 0; } + { + $1->append ($3); + $$ = $1; + } ; class_enum : identifier '(' expression ')' - { $$ = 0; } + { $$ = new tree_classdef_enum ($1, $3); } ; // ============= @@ -1660,6 +1768,7 @@ curr_fcn_depth = 0; primary_fcn_scope = -1; curr_class_name = ""; + curr_package_name = ""; function_scopes.clear (); primary_fcn_ptr = 0; subfunction_names.clear (); @@ -1831,95 +1940,6 @@ } } -static tree_expression * -fold (tree_binary_expression *e) -{ - tree_expression *retval = e; - - unwind_protect frame; - - frame.protect_var (error_state); - frame.protect_var (warning_state); - - frame.protect_var (discard_error_messages); - frame.protect_var (discard_warning_messages); - - discard_error_messages = true; - discard_warning_messages = true; - - tree_expression *op1 = e->lhs (); - tree_expression *op2 = e->rhs (); - - if (op1->is_constant () && op2->is_constant ()) - { - octave_value tmp = e->rvalue1 (); - - if (! (error_state || warning_state)) - { - tree_constant *tc_retval - = new tree_constant (tmp, op1->line (), op1->column ()); - - std::ostringstream buf; - - tree_print_code tpc (buf); - - e->accept (tpc); - - tc_retval->stash_original_text (buf.str ()); - - delete e; - - retval = tc_retval; - } - } - - return retval; -} - -static tree_expression * -fold (tree_unary_expression *e) -{ - tree_expression *retval = e; - - unwind_protect frame; - - frame.protect_var (error_state); - frame.protect_var (warning_state); - - frame.protect_var (discard_error_messages); - frame.protect_var (discard_warning_messages); - - discard_error_messages = true; - discard_warning_messages = true; - - tree_expression *op = e->operand (); - - if (op->is_constant ()) - { - octave_value tmp = e->rvalue1 (); - - if (! (error_state || warning_state)) - { - tree_constant *tc_retval - = new tree_constant (tmp, op->line (), op->column ()); - - std::ostringstream buf; - - tree_print_code tpc (buf); - - e->accept (tpc); - - tc_retval->stash_original_text (buf.str ()); - - delete e; - - retval = tc_retval; - } - } - - return retval; -} - // Finish building a range. tree_expression * @@ -1975,8 +1995,6 @@ e->preserve_base (); delete e; - // FIXME -- need to attempt constant folding here - // too (we need a generic way to do that). retval = base; } } @@ -2189,10 +2207,7 @@ int l = tok_val->line (); int c = tok_val->column (); - tree_binary_expression *e - = maybe_compound_binary_expression (op1, op2, l, c, t); - - return fold (e); + return maybe_compound_binary_expression (op1, op2, l, c, t); } // Build a boolean expression. @@ -2221,10 +2236,7 @@ int l = tok_val->line (); int c = tok_val->column (); - tree_boolean_expression *e - = new tree_boolean_expression (op1, op2, l, c, t); - - return fold (e); + return new tree_boolean_expression (op1, op2, l, c, t); } // Build a prefix expression. @@ -2265,10 +2277,7 @@ int l = tok_val->line (); int c = tok_val->column (); - tree_prefix_expression *e - = new tree_prefix_expression (op1, l, c, t); - - return fold (e); + return new tree_prefix_expression (op1, l, c, t); } // Build a postfix expression. @@ -2305,10 +2314,7 @@ int l = tok_val->line (); int c = tok_val->column (); - tree_postfix_expression *e - = new tree_postfix_expression (op1, l, c, t); - - return fold (e); + return new tree_postfix_expression (op1, l, c, t); } // Build an unwind-protect command. @@ -3002,6 +3008,197 @@ lexer.looking_at_parameter_list = false; } +tree_funcall * +octave_base_parser::make_superclass_ref (const std::string& method_nm, + const std::string& package_nm, + const std::string& class_nm, + int l, int c) +{ + octave_value_list args; + + args(2) = class_nm; + args(1) = package_nm; + args(0) = method_nm; + + octave_value fcn + = symbol_table::find_built_in_function ("__superclass_reference__"); + + return new tree_funcall (fcn, args); +} + +tree_funcall * +octave_base_parser::make_meta_class_query (const std::string& package_nm, + const std::string& class_nm, + int l, int c) +{ + octave_value_list args; + + args(1) = class_nm; + args(0) = package_nm; + + octave_value fcn + = symbol_table::find_built_in_function ("__meta_class_query__"); + + return new tree_funcall (fcn, args); +} + +// A CLASSDEF block defines a class that has a constructor and other +// methods, but it is not an executable command. Parsing the block +// makes some changes in the symbol table (inserting the constructor +// and methods, and adding to the list of known objects) and creates +// a parse tree containing meta information about the class. + +tree_classdef * +octave_base_parser::make_classdef (token *tok_val, + tree_classdef_attribute_list *a, + tree_identifier *id, + tree_classdef_superclass_list *sc, + tree_classdef_body *body, token *end_tok, + octave_comment_list *lc) +{ + tree_classdef *retval = 0; + + std::string cls_name = id->name (); + + std::string nm = lexer.fcn_file_name; + + size_t pos = nm.find_last_of (file_ops::dir_sep_chars ()); + + if (pos != std::string::npos) + nm = lexer.fcn_file_name.substr (pos+1); + + if (nm != cls_name) + bison_error ("invalid classdef definition, the class name must match the file name"); + else if (end_token_ok (end_tok, token::classdef_end)) + { + octave_comment_list *tc = lexer.comment_buf.get_comment (); + + int l = tok_val->line (); + int c = tok_val->column (); + + retval = new tree_classdef (a, id, sc, body, lc, tc, + curr_package_name, l, c); + } + + if (! retval) + { + delete a; + delete id; + delete sc; + delete body; + } + + return retval; +} + +tree_classdef_properties_block * +octave_base_parser::make_classdef_properties_block (token *tok_val, + tree_classdef_attribute_list *a, + tree_classdef_property_list *plist, + token *end_tok, + octave_comment_list *lc) +{ + tree_classdef_properties_block *retval = 0; + + if (end_token_ok (end_tok, token::properties_end)) + { + octave_comment_list *tc = lexer.comment_buf.get_comment (); + + int l = tok_val->line (); + int c = tok_val->column (); + + retval = new tree_classdef_properties_block (a, plist, lc, tc, l, c); + } + else + { + delete a; + delete plist; + } + + return retval; +} + +tree_classdef_methods_block * +octave_base_parser::make_classdef_methods_block (token *tok_val, + tree_classdef_attribute_list *a, + tree_classdef_methods_list *mlist, + token *end_tok, + octave_comment_list *lc) +{ + tree_classdef_methods_block *retval = 0; + + if (end_token_ok (end_tok, token::methods_end)) + { + octave_comment_list *tc = lexer.comment_buf.get_comment (); + + int l = tok_val->line (); + int c = tok_val->column (); + + retval = new tree_classdef_methods_block (a, mlist, lc, tc, l, c); + } + else + { + delete a; + delete mlist; + } + + return retval; +} + +tree_classdef_events_block * +octave_base_parser::make_classdef_events_block (token *tok_val, + tree_classdef_attribute_list *a, + tree_classdef_events_list *elist, + token *end_tok, + octave_comment_list *lc) +{ + tree_classdef_events_block *retval = 0; + + if (end_token_ok (end_tok, token::events_end)) + { + octave_comment_list *tc = lexer.comment_buf.get_comment (); + + int l = tok_val->line (); + int c = tok_val->column (); + + retval = new tree_classdef_events_block (a, elist, lc, tc, l, c); + } + else + { + delete a; + delete elist; + } + + return retval; +} + +tree_classdef_enum_block * +octave_base_parser::make_classdef_enum_block (token *tok_val, + tree_classdef_attribute_list *a, + tree_classdef_enum_list *elist, + token *end_tok, + octave_comment_list *lc) +{ + tree_classdef_enum_block *retval = 0; + + if (end_token_ok (end_tok, token::enumeration_end)) + { + octave_comment_list *tc = lexer.comment_buf.get_comment (); + + int l = tok_val->line (); + int c = tok_val->column (); + + retval = new tree_classdef_enum_block (a, elist, lc, tc, l, c); + } + else + { + delete a; + delete elist; + } + + return retval; +} + // Make an index expression. tree_index_expression * @@ -3024,7 +3221,8 @@ int l = expr->line (); int c = expr->column (); - expr->mark_postfix_indexed (); + if (! expr->is_postfix_indexed ()) + expr->set_postfix_index (type); if (expr->is_index_expression ()) { @@ -3051,6 +3249,9 @@ int l = expr->line (); int c = expr->column (); + if (! expr->is_postfix_indexed ()) + expr->set_postfix_index ('.'); + if (expr->is_index_expression ()) { tree_index_expression *tmp = static_cast (expr); @@ -3070,13 +3271,17 @@ // Make an indirect reference expression with dynamic field name. tree_index_expression * -octave_base_parser::make_indirect_ref (tree_expression *expr, tree_expression *elt) +octave_base_parser::make_indirect_ref (tree_expression *expr, + tree_expression *elt) { tree_index_expression *retval = 0; int l = expr->line (); int c = expr->column (); + if (! expr->is_postfix_indexed ()) + expr->set_postfix_index ('.'); + if (expr->is_index_expression ()) { tree_index_expression *tmp = static_cast (expr); @@ -3464,6 +3669,7 @@ static octave_function * parse_fcn_file (const std::string& full_file, const std::string& file, const std::string& dispatch_type, + const std::string& package_name, bool require_file, bool force_script, bool autoload, bool relative_lookup, const std::string& warn_for) { @@ -3497,6 +3703,7 @@ octave_parser parser (ffile); parser.curr_class_name = dispatch_type; + parser.curr_package_name = package_name; parser.autoloading = autoload; parser.fcn_file_from_relative_lookup = relative_lookup; @@ -3511,20 +3718,34 @@ fcn_ptr = parser.primary_fcn_ptr; - if (fcn_ptr) + if (status == 0) { - fcn_ptr->maybe_relocate_end (); - - if (parser.parsing_subfunctions) + if (parser.lexer.reading_classdef_file + && parser.classdef_object) { - if (! parser.endfunction_found) - parser.subfunction_names.reverse (); - - fcn_ptr->stash_subfunction_names (parser.subfunction_names); + // Convert parse tree for classdef object to + // meta.class info (and stash it in the symbol + // table?). Return pointer to constructor? + + if (fcn_ptr) + panic_impossible (); + + fcn_ptr = parser.classdef_object->make_meta_class (); + } + else if (fcn_ptr) + { + fcn_ptr->maybe_relocate_end (); + + if (parser.parsing_subfunctions) + { + if (! parser.endfunction_found) + parser.subfunction_names.reverse (); + + fcn_ptr->stash_subfunction_names (parser.subfunction_names); + } } } - - if (status != 0) + else error ("parse error while reading file %s", full_file.c_str ()); } else if (require_file) @@ -3565,7 +3786,8 @@ symbol_found = true; octave_function *fcn - = parse_fcn_file (full_file, file, "", true, false, false, false, ""); + = parse_fcn_file (full_file, file, "", "", true, false, false, false, + ""); if (fcn) { @@ -3629,6 +3851,7 @@ octave_function * load_fcn_from_file (const std::string& file_name, const std::string& dir_name, const std::string& dispatch_type, + const std::string& package_name, const std::string& fcn_name, bool autoload) { octave_function *retval = 0; @@ -3676,7 +3899,8 @@ // to get the help-string to use. octave_function *tmpfcn = parse_fcn_file (file.substr (0, len - 2), - nm, dispatch_type, false, + nm, dispatch_type, + package_name, false, autoload, autoload, relative_lookup, ""); @@ -3688,8 +3912,8 @@ } else if (len > 2) { - retval = parse_fcn_file (file, nm, dispatch_type, true, autoload, - autoload, relative_lookup, ""); + retval = parse_fcn_file (file, nm, dispatch_type, package_name, true, + autoload, autoload, relative_lookup, ""); } if (retval) @@ -3903,7 +4127,7 @@ if (! error_state) { octave_function *fcn = parse_fcn_file (file_full_name, file_name, - "", require_file, true, + "", "", require_file, true, false, false, warn_for); if (! error_state) @@ -4626,7 +4850,7 @@ if (nargin == 2) octave_stdout << "parsing " << full_file << std::endl; - octave_function *fcn = parse_fcn_file (full_file, file, "", + octave_function *fcn = parse_fcn_file (full_file, file, "", "", true, false, false, false, "__parse_file__"); diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/octave.gperf --- a/libinterp/parse-tree/octave.gperf Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/parse-tree/octave.gperf Tue Jan 07 16:07:54 2014 -0500 @@ -64,7 +64,6 @@ properties_kw, return_kw, set_kw, - static_kw, switch_kw, try_kw, until_kw, @@ -111,7 +110,6 @@ properties, PROPERTIES, properties_kw return, FUNC_RET, return_kw set, SET, set_kw -static, PERSISTENT, static_kw switch, SWITCH, switch_kw try, TRY, try_kw until, UNTIL, until_kw diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/parse.h --- a/libinterp/parse-tree/parse.h Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/parse-tree/parse.h Tue Jan 07 16:07:54 2014 -0500 @@ -43,6 +43,18 @@ class tree_argument_list; class tree_array_list; class tree_cell; +class tree_classdef; +class tree_classdef_attribute_list; +class tree_classdef_body; +class tree_classdef_enum_block; +class tree_classdef_enum_list; +class tree_classdef_events_block; +class tree_classdef_events_list; +class tree_classdef_methods_block; +class tree_classdef_methods_list; +class tree_classdef_properties_block; +class tree_classdef_property_list; +class tree_classdef_superclass_list; class tree_colon_expression; class tree_command; class tree_constant; @@ -50,6 +62,7 @@ class tree_decl_init_list; class tree_expression; class tree_fcn_handle; +class tree_funcall; class tree_function_def; class tree_identifier; class tree_if_clause; @@ -92,6 +105,7 @@ load_fcn_from_file (const std::string& file_name, const std::string& dir_name = std::string (), const std::string& dispatch_type = std::string (), + const std::string& package_name = std::string (), const std::string& fcn_name = std::string (), bool autoload = false); @@ -136,9 +150,9 @@ autoloading (false), fcn_file_from_relative_lookup (false), parsing_subfunctions (false), max_fcn_depth (0), curr_fcn_depth (0), primary_fcn_scope (-1), - curr_class_name (), function_scopes (), primary_fcn_ptr (0), - subfunction_names (), stmt_list (0), - lexer (lxr) + curr_class_name (), curr_package_name (), function_scopes (), + primary_fcn_ptr (0), subfunction_names (), classdef_object (0), + stmt_list (0), lexer (lxr) { } ~octave_base_parser (void); @@ -284,6 +298,47 @@ void recover_from_parsing_function (void); + tree_funcall * + make_superclass_ref (const std::string& method_nm, + const std::string& package_nm, + const std::string& class_nm, + int l, int c); + + tree_funcall * + make_meta_class_query (const std::string& package_nm, + const std::string& class_nm, + int l, int c); + + tree_classdef * + make_classdef (token *tok_val, tree_classdef_attribute_list *a, + tree_identifier *id, tree_classdef_superclass_list *sc, + tree_classdef_body *body, token *end_tok, + octave_comment_list *lc); + + tree_classdef_properties_block * + make_classdef_properties_block (token *tok_val, + tree_classdef_attribute_list *a, + tree_classdef_property_list *plist, + token *end_tok, octave_comment_list *lc); + + tree_classdef_methods_block * + make_classdef_methods_block (token *tok_val, + tree_classdef_attribute_list *a, + tree_classdef_methods_list *mlist, + token *end_tok, octave_comment_list *lc); + + tree_classdef_events_block * + make_classdef_events_block (token *tok_val, + tree_classdef_attribute_list *a, + tree_classdef_events_list *elist, + token *end_tok, octave_comment_list *lc); + + tree_classdef_enum_block * + make_classdef_enum_block (token *tok_val, + tree_classdef_attribute_list *a, + tree_classdef_enum_list *elist, + token *end_tok, octave_comment_list *lc); + // Make an index expression. tree_index_expression * make_index_expression (tree_expression *expr, @@ -372,6 +427,10 @@ // constructors. std::string curr_class_name; + // Name of the current package when we are parsing an element contained + // in a package directory (+-directory). + std::string curr_package_name; + // 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 @@ -385,6 +444,9 @@ // file. Eventually stashed in the primary function object. std::list subfunction_names; + // Pointer to the classdef object we just parsed, if any. + tree_classdef *classdef_object; + // Result of parsing input. tree_statement_list *stmt_list; diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/pt-all.h --- a/libinterp/parse-tree/pt-all.h Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/parse-tree/pt-all.h Tue Jan 07 16:07:54 2014 -0500 @@ -30,6 +30,7 @@ #include "pt-binop.h" #include "pt-cbinop.h" #include "pt-check.h" +#include "pt-classdef.h" #include "pt-cmd.h" #include "pt-colon.h" #include "pt-const.h" @@ -37,6 +38,7 @@ #include "pt-except.h" #include "pt-exp.h" #include "pt-fcn-handle.h" +#include "pt-funcall.h" #include "pt-id.h" #include "pt-idx.h" #include "pt-jump.h" diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/pt-bp.cc --- a/libinterp/parse-tree/pt-bp.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/parse-tree/pt-bp.cc Tue Jan 07 16:07:54 2014 -0500 @@ -293,6 +293,12 @@ } void +tree_breakpoint::visit_funcall (tree_funcall&) +{ + panic_impossible (); +} + +void tree_breakpoint::visit_parameter_list (tree_parameter_list&) { panic_impossible (); diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/pt-bp.h --- a/libinterp/parse-tree/pt-bp.h Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/parse-tree/pt-bp.h Tue Jan 07 16:07:54 2014 -0500 @@ -106,6 +106,8 @@ void visit_fcn_handle (tree_fcn_handle&); + void visit_funcall (tree_funcall&); + void visit_parameter_list (tree_parameter_list&); void visit_postfix_expression (tree_postfix_expression&); diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/pt-cbinop.cc --- a/libinterp/parse-tree/pt-cbinop.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/parse-tree/pt-cbinop.cc Tue Jan 07 16:07:54 2014 -0500 @@ -162,7 +162,8 @@ maybe_compound_binary_expression (tree_expression *a, tree_expression *b, int l, int c, octave_value::binary_op t) { - tree_expression *ca = a, *cb = b; + tree_expression *ca = a; + tree_expression *cb = b; octave_value::compound_binary_op ct; switch (t) diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/pt-check.cc --- a/libinterp/parse-tree/pt-check.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/parse-tree/pt-check.cc Tue Jan 07 16:07:54 2014 -0500 @@ -357,6 +357,11 @@ } void +tree_checker::visit_funcall (tree_funcall& /* fc */) +{ +} + +void tree_checker::visit_parameter_list (tree_parameter_list& lst) { tree_parameter_list::iterator p = lst.begin (); diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/pt-check.h --- a/libinterp/parse-tree/pt-check.h Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/parse-tree/pt-check.h Tue Jan 07 16:07:54 2014 -0500 @@ -91,6 +91,8 @@ void visit_fcn_handle (tree_fcn_handle&); + void visit_funcall (tree_funcall&); + void visit_parameter_list (tree_parameter_list&); void visit_postfix_expression (tree_postfix_expression&); diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/pt-classdef.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/parse-tree/pt-classdef.cc Tue Jan 07 16:07:54 2014 -0500 @@ -0,0 +1,259 @@ +/* + +Copyright (C) 2012-2013 John W. Eaton + +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 +. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "ov-classdef.h" +#include "pt-classdef.h" + +// Classdef attribute + +void +tree_classdef_attribute::accept (tree_walker& tw) +{ + tw.visit_classdef_attribute (*this); +} + +// Classdef attribute_list + +tree_classdef_attribute_list::~tree_classdef_attribute_list (void) +{ + while (! empty ()) + { + iterator p = begin (); + delete *p; + erase (p); + } +} + +void +tree_classdef_attribute_list::accept (tree_walker& tw) +{ + tw.visit_classdef_attribute_list (*this); +} + +// Classdef superclass + +void +tree_classdef_superclass::accept (tree_walker& tw) +{ + tw.visit_classdef_superclass (*this); +} + +// Classdef superclass_list + +tree_classdef_superclass_list::~tree_classdef_superclass_list (void) +{ + while (! empty ()) + { + iterator p = begin (); + delete *p; + erase (p); + } +} + +void +tree_classdef_superclass_list::accept (tree_walker& tw) +{ + tw.visit_classdef_superclass_list (*this); +} + +// Classdef property + +void +tree_classdef_property::accept (tree_walker& tw) +{ + tw.visit_classdef_property (*this); +} + +// Classdef property_list + +tree_classdef_property_list::~tree_classdef_property_list (void) +{ + while (! empty ()) + { + iterator p = begin (); + delete *p; + erase (p); + } +} + +void +tree_classdef_property_list::accept (tree_walker& tw) +{ + tw.visit_classdef_property_list (*this); +} + +// Classdef properties_block + +void +tree_classdef_properties_block::accept (tree_walker& tw) +{ + tw.visit_classdef_properties_block (*this); +} + +// Classdef methods_list + +void +tree_classdef_methods_list::accept (tree_walker& tw) +{ + tw.visit_classdef_methods_list (*this); +} + +// Classdef methods_block + +void +tree_classdef_methods_block::accept (tree_walker& tw) +{ + tw.visit_classdef_methods_block (*this); +} + +// Classdef event + +void +tree_classdef_event::accept (tree_walker& tw) +{ + tw.visit_classdef_event (*this); +} + +// Classdef events_list + +tree_classdef_events_list::~tree_classdef_events_list (void) +{ + while (! empty ()) + { + iterator p = begin (); + delete *p; + erase (p); + } +} + +void +tree_classdef_events_list::accept (tree_walker& tw) +{ + tw.visit_classdef_events_list (*this); +} + +// Classdef events_block + +void +tree_classdef_events_block::accept (tree_walker& tw) +{ + tw.visit_classdef_events_block (*this); +} + +// Classdef enum + +void +tree_classdef_enum::accept (tree_walker& tw) +{ + tw.visit_classdef_enum (*this); +} + +// Classdef enum_list + +tree_classdef_enum_list::~tree_classdef_enum_list (void) +{ + while (! empty ()) + { + iterator p = begin (); + delete *p; + erase (p); + } +} + +void +tree_classdef_enum_list::accept (tree_walker& tw) +{ + tw.visit_classdef_enum_list (*this); +} + +// Classdef enum_block + +void +tree_classdef_enum_block::accept (tree_walker& tw) +{ + tw.visit_classdef_enum_block (*this); +} + +// Classdef body + +tree_classdef_body::~tree_classdef_body (void) +{ + while (! properties_lst.empty ()) + { + properties_list_iterator p = properties_lst.begin (); + delete *p; + properties_lst.erase (p); + } + + while (! methods_lst.empty ()) + { + methods_list_iterator p = methods_lst.begin (); + delete *p; + methods_lst.erase (p); + } + + while (! events_lst.empty ()) + { + events_list_iterator p = events_lst.begin (); + delete *p; + events_lst.erase (p); + } + + while (! enum_lst.empty ()) + { + enum_list_iterator p = enum_lst.begin (); + delete *p; + enum_lst.erase (p); + } +} + +// Classdef + +octave_function* +tree_classdef::make_meta_class (void) +{ + octave_value retval; + cdef_class cls = cdef_class::make_meta_class (this); + + if (cls.ok ()) + return cls.get_constructor_function (); + + return 0; +} + +tree_classdef * +tree_classdef::dup (symbol_table::scope_id, + symbol_table::context_id) const +{ + // FIXME + return 0; +} + +void +tree_classdef::accept (tree_walker& tw) +{ + tw.visit_classdef (*this); +} diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/pt-classdef.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/parse-tree/pt-classdef.h Tue Jan 07 16:07:54 2014 -0500 @@ -0,0 +1,660 @@ +/* + +Copyright (C) 2012-2013 John W. Eaton + +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 +. + +*/ + +#if !defined (octave_tree_classdef_h) +#define octave_tree_classdef_h 1 + +class octave_value; + +class tree_walker; + +#include "pt-cmd.h" +#include "pt-exp.h" +#include "pt-id.h" + +#include "base-list.h" + +#include + +class tree_classdef_attribute +{ +public: + + tree_classdef_attribute (tree_identifier *i = 0, tree_expression *e = 0) + : id (i), expr (e), neg (false) { } + + tree_classdef_attribute (tree_identifier *i, bool b) + : id (i), expr (0), neg (b) { } + + ~tree_classdef_attribute (void) + { + delete id; + delete expr; + } + + tree_identifier *ident (void) { return id; } + + tree_expression *expression (void) { return expr; } + + bool negate (void) { return neg; } + + void accept (tree_walker&); + +private: + + tree_identifier *id; + tree_expression *expr; + bool neg; + + // No copying! + + tree_classdef_attribute (const tree_classdef_attribute&); + + tree_classdef_attribute& operator = (const tree_classdef_attribute&); +}; + +class tree_classdef_attribute_list : public octave_base_list +{ +public: + + tree_classdef_attribute_list (void) { } + + tree_classdef_attribute_list (tree_classdef_attribute *a) { append (a); } + + tree_classdef_attribute_list (const octave_base_list& a) + : octave_base_list (a) { } + + ~tree_classdef_attribute_list (void); + + void accept (tree_walker&); + +private: + + // No copying! + + tree_classdef_attribute_list (const tree_classdef_attribute_list&); + + tree_classdef_attribute_list& operator = (const tree_classdef_attribute_list&); +}; + +class tree_classdef_superclass +{ +public: + + tree_classdef_superclass (tree_identifier *i = 0, tree_identifier *p = 0) + : id (i), pkg (p) { } + + ~tree_classdef_superclass (void) + { + delete id; + delete pkg; + } + + tree_identifier *ident (void) { return id; } + + tree_identifier * package (void) { return pkg; } + + void accept (tree_walker&); + +private: + + tree_identifier *id; + tree_identifier *pkg; + + // No copying! + + tree_classdef_superclass (const tree_classdef_superclass&); + + tree_classdef_superclass& operator = (const tree_classdef_superclass&); +}; + +class tree_classdef_superclass_list : public octave_base_list +{ +public: + + tree_classdef_superclass_list (void) { } + + tree_classdef_superclass_list (tree_classdef_superclass *sc) { append (sc); } + + tree_classdef_superclass_list (const octave_base_list& a) + : octave_base_list (a) { } + + ~tree_classdef_superclass_list (void); + + void accept (tree_walker&); + +private: + + // No copying! + + tree_classdef_superclass_list (const tree_classdef_superclass_list&); + + tree_classdef_superclass_list& operator = (const tree_classdef_superclass_list&); +}; + +template +class tree_classdef_element : public tree +{ +public: + + tree_classdef_element (tree_classdef_attribute_list *a, + octave_base_list *elist, + octave_comment_list *lc, octave_comment_list *tc, + int l = -1, int c = -1) + : tree (l, c), attr_list (a), elt_list (elist), + lead_comm (lc), trail_comm (tc) + { } + + ~tree_classdef_element (void) + { + delete attr_list; + delete elt_list; + delete lead_comm; + delete trail_comm; + } + + tree_classdef_attribute_list *attribute_list (void) { return attr_list; } + + octave_base_list *element_list (void) { return elt_list; } + + octave_comment_list *leading_comment (void) { return lead_comm; } + + octave_comment_list *trailing_comment (void) { return trail_comm; } + + void accept (tree_walker&) { } + +private: + + // List of attributes that apply to this class. + tree_classdef_attribute_list *attr_list; + + // The list of objects contained in this block. + octave_base_list *elt_list; + + // Comment preceding the token marking the beginning of the block. + octave_comment_list *lead_comm; + + // Comment preceding END token. + octave_comment_list *trail_comm; + + // No copying! + + tree_classdef_element (const tree_classdef_element&); + + tree_classdef_element& operator = (const tree_classdef_element&); +}; + +class tree_classdef_property +{ +public: + + tree_classdef_property (tree_identifier *i = 0, tree_expression *e = 0) + : id (i), expr (e) { } + + ~tree_classdef_property (void) + { + delete id; + delete expr; + } + + tree_identifier *ident (void) { return id; } + + tree_expression *expression (void) { return expr; } + + void accept (tree_walker&); + +private: + + tree_identifier *id; + tree_expression *expr; + + // No copying! + + tree_classdef_property (const tree_classdef_property&); + + tree_classdef_property& operator = (const tree_classdef_property&); +}; + +class tree_classdef_property_list : public octave_base_list +{ +public: + + tree_classdef_property_list (void) { } + + tree_classdef_property_list (tree_classdef_property* p) { append (p); } + + tree_classdef_property_list (const octave_base_list& a) + : octave_base_list (a) { } + + ~tree_classdef_property_list (void); + + void accept (tree_walker&); + +private: + + // No copying! + + tree_classdef_property_list (const tree_classdef_property_list&); + + tree_classdef_property_list& operator = (const tree_classdef_property_list&); +}; + +class tree_classdef_properties_block + : public tree_classdef_element +{ +public: + + tree_classdef_properties_block (tree_classdef_attribute_list *a, + tree_classdef_property_list *plist, + octave_comment_list *lc, + octave_comment_list *tc, + int l = -1, int c = -1) + : tree_classdef_element (a, plist, lc, tc, l, c) { } + + ~tree_classdef_properties_block (void) { } + + void accept (tree_walker&); + +private: + + // No copying! + + tree_classdef_properties_block (const tree_classdef_properties_block&); + + tree_classdef_properties_block& operator = (const tree_classdef_properties_block&); +}; + +class tree_classdef_methods_list : public octave_base_list +{ +public: + + tree_classdef_methods_list (void) { } + + tree_classdef_methods_list (const octave_value& f) { append (f); } + + tree_classdef_methods_list (const octave_base_list& a) + : octave_base_list (a) { } + + ~tree_classdef_methods_list (void) { } + + void accept (tree_walker&); + +private: + + // No copying! + + tree_classdef_methods_list (const tree_classdef_methods_list&); + + tree_classdef_methods_list& operator = (const tree_classdef_methods_list&); +}; + +class tree_classdef_methods_block : public tree_classdef_element +{ +public: + + tree_classdef_methods_block (tree_classdef_attribute_list *a, + tree_classdef_methods_list *mlist, + octave_comment_list *lc, + octave_comment_list *tc, int l = -1, int c = -1) + : tree_classdef_element (a, mlist, lc, tc, l, c) { } + + ~tree_classdef_methods_block (void) { } + + void accept (tree_walker&); + +private: + + // No copying! + + tree_classdef_methods_block (const tree_classdef_methods_block&); + + tree_classdef_methods_block& operator = (const tree_classdef_methods_block&); +}; + +class tree_classdef_event +{ +public: + + tree_classdef_event (tree_identifier *i = 0) : id (i) { } + + ~tree_classdef_event (void) + { + delete id; + } + + tree_identifier *ident (void) { return id; } + + void accept (tree_walker&); + +private: + + tree_identifier *id; + + // No copying! + + tree_classdef_event (const tree_classdef_event&); + + tree_classdef_event& operator = (const tree_classdef_event&); +}; + +class tree_classdef_events_list : public octave_base_list +{ +public: + + tree_classdef_events_list (void) { } + + tree_classdef_events_list (tree_classdef_event *e) { append (e); } + + tree_classdef_events_list (const octave_base_list& a) + : octave_base_list (a) { } + + ~tree_classdef_events_list (void); + + void accept (tree_walker&); + +private: + + // No copying! + + tree_classdef_events_list (const tree_classdef_events_list&); + + tree_classdef_events_list& operator = (const tree_classdef_events_list&); +}; + +class tree_classdef_events_block + : public tree_classdef_element +{ +public: + + tree_classdef_events_block (tree_classdef_attribute_list *a, + tree_classdef_events_list *elist, + octave_comment_list *lc, + octave_comment_list *tc, int l = -1, int c = -1) + : tree_classdef_element (a, elist, lc, tc, l, c) { } + + ~tree_classdef_events_block (void) { } + + void accept (tree_walker&); + +private: + + // No copying! + + tree_classdef_events_block (const tree_classdef_events_block&); + + tree_classdef_events_block& operator = (const tree_classdef_events_block&); +}; + +class tree_classdef_enum +{ +public: + + tree_classdef_enum (void) : id (0), expr (0) { } + + tree_classdef_enum (tree_identifier *i, tree_expression *e) + : id (i), expr (e) { } + + ~tree_classdef_enum (void) + { + delete id; + delete expr; + } + + tree_identifier *ident (void) { return id; } + + tree_expression *expression (void) { return expr; } + + void accept (tree_walker&); + +private: + + tree_identifier *id; + tree_expression *expr; + + // No copying! + + tree_classdef_enum (const tree_classdef_enum&); + + tree_classdef_enum& operator = (const tree_classdef_enum&); +}; + +class tree_classdef_enum_list : public octave_base_list +{ +public: + + tree_classdef_enum_list (void) { } + + tree_classdef_enum_list (tree_classdef_enum *e) { append (e); } + + tree_classdef_enum_list (const octave_base_list& a) + : octave_base_list (a) { } + + ~tree_classdef_enum_list (void); + + void accept (tree_walker&); + +private: + + // No copying! + + tree_classdef_enum_list (const tree_classdef_enum_list&); + + tree_classdef_enum_list& operator = (const tree_classdef_enum_list&); +}; + +class tree_classdef_enum_block + : public tree_classdef_element +{ +public: + + tree_classdef_enum_block (tree_classdef_attribute_list *a, + tree_classdef_enum_list *elist, + octave_comment_list *lc, + octave_comment_list *tc, int l = -1, int c = -1) + : tree_classdef_element (a, elist, lc, tc, l, c) { } + + ~tree_classdef_enum_block (void) { } + + void accept (tree_walker&); + +private: + + // No copying! + + tree_classdef_enum_block (const tree_classdef_enum_block&); + + tree_classdef_enum_block& operator = (const tree_classdef_enum_block&); +}; + +class tree_classdef_body +{ +public: + + typedef std::list::iterator properties_list_iterator; + typedef std::list::const_iterator properties_list_const_iterator; + + typedef std::list::iterator methods_list_iterator; + typedef std::list::const_iterator methods_list_const_iterator; + + typedef std::list::iterator events_list_iterator; + typedef std::list::const_iterator events_list_const_iterator; + + typedef std::list::iterator enum_list_iterator; + typedef std::list::const_iterator enum_list_const_iterator; + + tree_classdef_body (void) + : properties_lst (), methods_lst (), events_lst (), enum_lst () { } + + tree_classdef_body (tree_classdef_properties_block *pb) + : properties_lst (), methods_lst (), events_lst (), enum_lst () + { + append (pb); + } + + tree_classdef_body (tree_classdef_methods_block *mb) + : properties_lst (), methods_lst (), events_lst (), enum_lst () + { + append (mb); + } + + tree_classdef_body (tree_classdef_events_block *evb) + : properties_lst (), methods_lst (), events_lst (), enum_lst () + { + append (evb); + } + + tree_classdef_body (tree_classdef_enum_block *enb) + : properties_lst (), methods_lst (), events_lst (), enum_lst () + { + append (enb); + } + + ~tree_classdef_body (void); + + void append (tree_classdef_properties_block *pb) + { + properties_lst.push_back (pb); + } + + void append (tree_classdef_methods_block *mb) + { + methods_lst.push_back (mb); + } + + void append (tree_classdef_events_block *evb) + { + events_lst.push_back (evb); + } + + void append (tree_classdef_enum_block *enb) + { + enum_lst.push_back (enb); + } + + std::list properties_list (void) + { + return properties_lst; + } + + std::list methods_list (void) + { + return methods_lst; + } + + std::list events_list (void) + { + return events_lst; + } + + std::list enum_list (void) + { + return enum_lst; + } + + void accept (tree_walker&); + +private: + + std::list properties_lst; + + std::list methods_lst; + + std::list events_lst; + + std::list enum_lst; + + // No copying! + + tree_classdef_body (const tree_classdef_body&); + + tree_classdef_body& operator = (const tree_classdef_body&); +}; + +// Classdef definition. + +class tree_classdef : public tree_command +{ +public: + + tree_classdef (tree_classdef_attribute_list *a, tree_identifier *i, + tree_classdef_superclass_list *sc, + tree_classdef_body *b, octave_comment_list *lc, + octave_comment_list *tc, + const std::string& pn = std::string (), int l = -1, + int c = -1) + : tree_command (l, c), attr_list (a), id (i), + supclass_list (sc), element_list (b), lead_comm (lc), trail_comm (tc), + pack_name (pn) { } + + ~tree_classdef (void) + { + delete attr_list; + delete id; + delete supclass_list; + delete element_list; + delete lead_comm; + delete trail_comm; + } + + tree_classdef_attribute_list *attribute_list (void) { return attr_list; } + + tree_identifier *ident (void) { return id; } + + tree_classdef_superclass_list *superclass_list (void) { return supclass_list; } + + tree_classdef_body *body (void) { return element_list; } + + octave_comment_list *leading_comment (void) { return lead_comm; } + octave_comment_list *trailing_comment (void) { return trail_comm; } + + const std::string& package_name (void) const { return pack_name; } + + octave_function* make_meta_class (void); + + tree_classdef *dup (symbol_table::scope_id scope, + symbol_table::context_id context) const; + + void accept (tree_walker& tw); + +private: + + tree_classdef_attribute_list *attr_list; + + tree_identifier *id; + + tree_classdef_superclass_list *supclass_list; + + tree_classdef_body *element_list; + + octave_comment_list *lead_comm; + octave_comment_list *trail_comm; + + std::string pack_name; + + // No copying! + + tree_classdef (const tree_classdef&); + + tree_classdef& operator = (const tree_classdef&); +}; + +#endif diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/pt-eval.cc --- a/libinterp/parse-tree/pt-eval.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/parse-tree/pt-eval.cc Tue Jan 07 16:07:54 2014 -0500 @@ -379,7 +379,8 @@ dim_vector dv = rhs.dims ().redim (2); - octave_idx_type nrows = dv(0), steps = dv(1); + octave_idx_type nrows = dv(0); + octave_idx_type steps = dv(1); if (steps > 0) { @@ -637,6 +638,12 @@ } void +tree_evaluator::visit_funcall (tree_funcall&) +{ + panic_impossible (); +} + +void tree_evaluator::visit_parameter_list (tree_parameter_list&) { panic_impossible (); diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/pt-eval.h --- a/libinterp/parse-tree/pt-eval.h Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/parse-tree/pt-eval.h Tue Jan 07 16:07:54 2014 -0500 @@ -102,6 +102,8 @@ void visit_fcn_handle (tree_fcn_handle&); + void visit_funcall (tree_funcall&); + void visit_parameter_list (tree_parameter_list&); void visit_postfix_expression (tree_postfix_expression&); diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/pt-exp.h --- a/libinterp/parse-tree/pt-exp.h Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/parse-tree/pt-exp.h Tue Jan 07 16:07:54 2014 -0500 @@ -40,7 +40,7 @@ public: tree_expression (int l = -1, int c = -1) - : tree (l, c), num_parens (0), postfix_indexed (false), + : tree (l, c), num_parens (0), postfix_index_type ('\0'), print_flag (false) { } virtual ~tree_expression (void) { } @@ -87,7 +87,9 @@ int paren_count (void) const { return num_parens; } - bool is_postfix_indexed (void) const { return postfix_indexed; } + bool is_postfix_indexed (void) const { return (postfix_index_type != '\0'); } + + char postfix_index (void) const { return postfix_index_type; } // Check if the result of the expression should be printed. // Should normally be used in conjunction with @@ -108,9 +110,9 @@ return this; } - tree_expression *mark_postfix_indexed (void) + tree_expression *set_postfix_index (char type) { - postfix_indexed = true; + postfix_index_type = type; return this; } @@ -123,7 +125,7 @@ virtual void copy_base (const tree_expression& e) { num_parens = e.num_parens; - postfix_indexed = e.postfix_indexed; + postfix_index_type = e.postfix_index_type; print_flag = e.print_flag; } @@ -137,9 +139,10 @@ // ==> 0 for expression e2 int num_parens; - // A flag that says whether this expression has an index associated - // with it. See the code in tree_identifier::rvalue for the rationale. - bool postfix_indexed; + // The first index type associated with this expression. This field + // is 0 (character '\0') if the expression has no associated index. + // See the code in tree_identifier::rvalue for the rationale. + char postfix_index_type; // Print result of rvalue for this expression? bool print_flag; diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/pt-funcall.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/parse-tree/pt-funcall.cc Tue Jan 07 16:07:54 2014 -0500 @@ -0,0 +1,83 @@ +/* + +Copyright (C) 2012-2013 John W. Eaton + +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 +. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "ov-fcn.h" +#include "pt-funcall.h" +#include "pt-walk.h" + +// Function call objects. + +void +tree_funcall::print (std::ostream& os, bool pr_as_read_syntax, + bool pr_orig_text) +{ + print_raw (os, pr_as_read_syntax, pr_orig_text); +} + +void +tree_funcall::print_raw (std::ostream& os, bool pr_as_read_syntax, + bool pr_orig_text) +{ + if (pr_orig_text) + { + os << original_text (); + } + else + { + octave_function *fp = fcn.function_value (); + std::string nm = fp ? fp->name () : std::string (""); + + os << nm << " ("; + + octave_idx_type len = args.length (); + for (octave_idx_type i = 0; i < len; i++) + { + args(i).print_raw (os, pr_as_read_syntax); + + if (i < len - 1) + os << ", "; + } + + os << ")"; + } +} + +tree_funcall * +tree_funcall::dup (symbol_table::scope_id, + symbol_table::context_id context) const +{ + tree_funcall *new_fc = new tree_funcall (fcn, args, line (), column ()); + + new_fc->copy_base (*new_fc); + + return new_fc; +} + +void +tree_funcall::accept (tree_walker& tw) +{ + tw.visit_funcall (*this); +} diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/pt-funcall.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/parse-tree/pt-funcall.h Tue Jan 07 16:07:54 2014 -0500 @@ -0,0 +1,101 @@ +/* + +Copyright (C) 2012-2013 John W. Eaton + +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 +. + +*/ + +#if !defined (octave_tree_funcall_h) +#define octave_tree_funcall_h 1 + +#include "ov.h" +#include "oct-obj.h" +#include "parse.h" +#include "pt-exp.h" + +// Function call. This class only represents function calls that have +// known functions (most useful for calls to built-in functions that +// are generated by the parser) and fixed argument lists, known at +// compile time. + +class +tree_funcall : public tree_expression +{ +public: + + tree_funcall (const octave_value& f, const octave_value_list& a, + int l = -1, int c = -1) + : tree_expression (l, c), fcn (f), args (a) + { + if (! fcn.is_function ()) + error ("tree_funcall: invalid function"); + } + + ~tree_funcall (void) { } + + bool has_magic_end (void) const { return false; } + + void print (std::ostream& os, bool pr_as_read_syntax = false, + bool pr_orig_txt = true); + + void print_raw (std::ostream& os, bool pr_as_read_syntax = false, + bool pr_orig_txt = true); + + tree_funcall *dup (symbol_table::scope_id, + symbol_table::context_id context) const; + + octave_value rvalue1 (int nargout) + { + octave_value retval; + + const octave_value_list tmp = rvalue (nargout); + + if (! tmp.empty ()) + retval = tmp(0); + + return retval; + } + + octave_value_list rvalue (int nargout) + { + return feval (fcn.function_value (), args, nargout); + } + + octave_value function (void) const { return fcn; } + + octave_value_list arguments (void) const { return args; } + + void accept (tree_walker& tw); + +private: + + // Function to call. Error if not a valid function at time of + // construction. + octave_value fcn; + + // Argument list. + octave_value_list args; + + // No copying! + + tree_funcall (const tree_funcall&); + + tree_funcall& operator = (const tree_funcall&); +}; + +#endif diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/pt-id.cc --- a/libinterp/parse-tree/pt-id.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/parse-tree/pt-id.cc Tue Jan 07 16:07:54 2014 -0500 @@ -76,13 +76,19 @@ // // If this identifier refers to a function, we need to know // whether it is indexed so that we can do the same thing - // for 'f' and 'f()'. If the index is present, return the - // function object and let tree_index_expression::rvalue - // handle indexing. Otherwise, arrange to call the function - // here, so that we don't return the function definition as - // a value. + // for 'f' and 'f()'. If the index is present and the function + // object declares it can handle it, return the function object + // and let tree_index_expression::rvalue handle indexing. + // Otherwise, arrange to call the function here, so that we don't + // return the function definition as a value. - if (val.is_function () && ! is_postfix_indexed ()) + octave_function *fcn = 0; + + if (val.is_function ()) + fcn = val.function_value (true); + + if (fcn && ! (is_postfix_indexed () + && fcn->is_postfix_index_handled (postfix_index ()))) { octave_value_list tmp_args; diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/pt-id.h --- a/libinterp/parse-tree/pt-id.h Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/parse-tree/pt-id.h Tue Jan 07 16:07:54 2014 -0500 @@ -32,6 +32,7 @@ class tree_walker; +#include "oct-lvalue.h" #include "pt-bp.h" #include "pt-exp.h" #include "symtab.h" diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/pt-mat.cc --- a/libinterp/parse-tree/pt-mat.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/parse-tree/pt-mat.cc Tue Jan 07 16:07:54 2014 -0500 @@ -683,7 +683,8 @@ single_type_concat (Array& result, tm_const& tmp) { - octave_idx_type r = 0, c = 0; + octave_idx_type r = 0; + octave_idx_type c = 0; for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++) { @@ -753,7 +754,8 @@ return; } - octave_idx_type ncols = row.length (), i = 0; + octave_idx_type ncols = row.length (); + octave_idx_type i = 0; OCTAVE_LOCAL_BUFFER (Array, array_list, ncols); for (tm_row_const::iterator q = row.begin (); @@ -791,12 +793,14 @@ // Sparse matrices require preallocation for efficient indexing; besides, // only horizontal concatenation can be efficiently handled by indexing. // So we just cat all rows through liboctave, then cat the final column. - octave_idx_type nrows = tmp.length (), j = 0; + octave_idx_type nrows = tmp.length (); + octave_idx_type j = 0; OCTAVE_LOCAL_BUFFER (Sparse, sparse_row_list, nrows); for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++) { tm_row_const row = *p; - octave_idx_type ncols = row.length (), i = 0; + octave_idx_type ncols = row.length (); + octave_idx_type i = 0; OCTAVE_LOCAL_BUFFER (Sparse, sparse_list, ncols); for (tm_row_const::iterator q = row.begin (); @@ -829,12 +833,14 @@ return; } - octave_idx_type nrows = tmp.length (), j = 0; + octave_idx_type nrows = tmp.length (); + octave_idx_type j = 0; OCTAVE_LOCAL_BUFFER (octave_map, map_row_list, nrows); for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++) { tm_row_const row = *p; - octave_idx_type ncols = row.length (), i = 0; + octave_idx_type ncols = row.length (); + octave_idx_type i = 0; OCTAVE_LOCAL_BUFFER (MAP, map_list, ncols); for (tm_row_const::iterator q = row.begin (); diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/pt-pr-code.cc --- a/libinterp/parse-tree/pt-pr-code.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/parse-tree/pt-pr-code.cc Tue Jan 07 16:07:54 2014 -0500 @@ -749,6 +749,18 @@ } void +tree_print_code::visit_funcall (tree_funcall& fc) +{ + indent (); + + print_parens (fc, "("); + + fc.print_raw (os, true, print_original_text); + + print_parens (fc, ")"); +} + +void tree_print_code::visit_parameter_list (tree_parameter_list& lst) { tree_parameter_list::iterator p = lst.begin (); diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/pt-pr-code.h --- a/libinterp/parse-tree/pt-pr-code.h Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/parse-tree/pt-pr-code.h Tue Jan 07 16:07:54 2014 -0500 @@ -109,6 +109,8 @@ void visit_fcn_handle (tree_fcn_handle&); + void visit_funcall (tree_funcall&); + void visit_parameter_list (tree_parameter_list&); void visit_postfix_expression (tree_postfix_expression&); diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/pt-walk.h --- a/libinterp/parse-tree/pt-walk.h Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/parse-tree/pt-walk.h Tue Jan 07 16:07:54 2014 -0500 @@ -52,6 +52,7 @@ class tree_no_op_command; class tree_constant; class tree_fcn_handle; +class tree_funcall; class tree_parameter_list; class tree_postfix_expression; class tree_prefix_expression; @@ -65,6 +66,24 @@ class tree_while_command; class tree_do_until_command; +class tree_classdef_attribute; +class tree_classdef_attribute_list; +class tree_classdef_superclass; +class tree_classdef_superclass_list; +class tree_classdef_property; +class tree_classdef_property_list; +class tree_classdef_properties_block; +class tree_classdef_methods_list; +class tree_classdef_methods_block; +class tree_classdef_event; +class tree_classdef_events_list; +class tree_classdef_events_block; +class tree_classdef_enum; +class tree_classdef_enum_list; +class tree_classdef_enum_block; +class tree_classdef_body; +class tree_classdef; + class tree_walker { @@ -158,6 +177,9 @@ visit_fcn_handle (tree_fcn_handle&) = 0; virtual void + visit_funcall (tree_funcall&) = 0; + + virtual void visit_parameter_list (tree_parameter_list&) = 0; virtual void @@ -193,6 +215,57 @@ virtual void visit_do_until_command (tree_do_until_command&) = 0; + virtual void + visit_classdef_attribute (tree_classdef_attribute&) { } /* = 0; */ + + virtual void + visit_classdef_attribute_list (tree_classdef_attribute_list&) { } /* = 0; */ + + virtual void + visit_classdef_superclass (tree_classdef_superclass&) { } /* = 0; */ + + virtual void + visit_classdef_superclass_list (tree_classdef_superclass_list&) { } /* = 0; */ + + virtual void + visit_classdef_property (tree_classdef_property&) { } /* = 0; */ + + virtual void + visit_classdef_property_list (tree_classdef_property_list&) { } /* = 0; */ + + virtual void + visit_classdef_properties_block (tree_classdef_properties_block&) { } /* = 0; */ + + virtual void + visit_classdef_methods_list (tree_classdef_methods_list&) { } /* = 0; */ + + virtual void + visit_classdef_methods_block (tree_classdef_methods_block&) { } /* = 0; */ + + virtual void + visit_classdef_event (tree_classdef_event&) { } /* = 0; */ + + virtual void + visit_classdef_events_list (tree_classdef_events_list&) { } /* = 0; */ + + virtual void + visit_classdef_events_block (tree_classdef_events_block&) { } /* = 0; */ + + virtual void + visit_classdef_enum (tree_classdef_enum&) { } /* = 0; */ + + virtual void + visit_classdef_enum_list (tree_classdef_enum_list&) { } /* = 0; */ + + virtual void + visit_classdef_enum_block (tree_classdef_enum_block&) { } /* = 0; */ + + virtual void + visit_classdef_body (tree_classdef_body&) { } /* = 0; */ + + virtual void + visit_classdef (tree_classdef&) { } /* = 0; */ + protected: tree_walker (void) { } diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/token.cc --- a/libinterp/parse-tree/token.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/parse-tree/token.cc Tue Jan 07 16:07:54 2014 -0500 @@ -97,38 +97,50 @@ sr = s; } -token::token (int tv, symbol_table::symbol_record *cls, - symbol_table::symbol_record *pkg, int l, int c) +token::token (int tv, const std::string& pkg, const std::string& cls, + int l, int c) +{ + maybe_cmd = false; + tspc = false; + line_num = l; + column_num = c; + tok_val = tv; + type_tag = meta_name_token; + mc.package_nm = new std::string (pkg); + mc.class_nm = new std::string (cls); +} + +token::token (int tv, const std::string& mth, const std::string& pkg, + const std::string& cls, int l, int c) { maybe_cmd = false; tspc = false; line_num = l; column_num = c; tok_val = tv; - type_tag = meta_rec_token; - mc.cr = cls; - mc.pr = pkg; -} - -token::token (int tv, symbol_table::symbol_record *mth, - symbol_table::symbol_record *cls, - symbol_table::symbol_record *pkg, int l, int c) -{ - maybe_cmd = false; - tspc = false; - line_num = l; - column_num = c; - tok_val = tv; - type_tag = scls_rec_token; - sc.mr = mth; - sc.cr = cls; - sc.pr = pkg; + type_tag = scls_name_token; + sc.method_nm = new std::string (mth); + sc.package_nm = new std::string (pkg); + sc.class_nm = new std::string (cls); } token::~token (void) { if (type_tag == string_token) delete str; + + if (type_tag == scls_name_token) + { + delete sc.method_nm; + delete sc.package_nm; + delete sc.class_nm; + } + + if (type_tag == meta_name_token) + { + delete mc.package_nm; + delete mc.class_nm; + } } std::string @@ -172,39 +184,39 @@ return sr; } -symbol_table::symbol_record * -token::method_rec (void) +std::string +token::superclass_method_name (void) { - assert (type_tag == scls_rec_token); - return sc.mr; + assert (type_tag == scls_name_token); + return *sc.method_nm; } -symbol_table::symbol_record * -token::class_rec (void) +std::string +token::superclass_package_name (void) { - assert (type_tag == scls_rec_token); - return sc.cr; + assert (type_tag == scls_name_token); + return *sc.package_nm; } -symbol_table::symbol_record * -token::package_rec (void) +std::string +token::superclass_class_name (void) { - assert (type_tag == scls_rec_token); - return sc.pr; + assert (type_tag == scls_name_token); + return *sc.class_nm; } -symbol_table::symbol_record * -token::meta_class_rec (void) +std::string +token::meta_package_name (void) { - assert (type_tag == meta_rec_token); - return mc.cr; + assert (type_tag == meta_name_token); + return *mc.package_nm; } -symbol_table::symbol_record * -token::meta_package_rec (void) +std::string +token::meta_class_name (void) { - assert (type_tag == meta_rec_token); - return mc.pr; + assert (type_tag == meta_name_token); + return *mc.class_nm; } std::string diff -r e42d4f152766 -r 8f256148d82b libinterp/parse-tree/token.h --- a/libinterp/parse-tree/token.h Tue Jan 07 16:07:21 2014 -0500 +++ b/libinterp/parse-tree/token.h Tue Jan 07 16:07:54 2014 -0500 @@ -40,8 +40,8 @@ double_token, ettype_token, sym_rec_token, - scls_rec_token, - meta_rec_token + scls_name_token, + meta_name_token }; enum end_tok_type @@ -69,11 +69,10 @@ int l = -1, int c = -1); token (int tv, end_tok_type t, int l = -1, int c = -1); token (int tv, symbol_table::symbol_record *s, int l = -1, int c = -1); - token (int tv, symbol_table::symbol_record *cls, - symbol_table::symbol_record *pkg, int l = -1, int c = -1); - token (int tv, symbol_table::symbol_record *mth, - symbol_table::symbol_record *cls, - symbol_table::symbol_record *pkg, int l = -1, int c = -1); + token (int tv, const std::string& pkg, const std::string& cls, + int l = -1, int c = -1); + token (int tv, const std::string& mth, const std::string& pkg, + const std::string& cls, int l = -1, int c = -1); ~token (void); @@ -106,12 +105,12 @@ end_tok_type ettype (void) const; symbol_table::symbol_record *sym_rec (void); - symbol_table::symbol_record *method_rec (void); - symbol_table::symbol_record *class_rec (void); - symbol_table::symbol_record *package_rec (void); + std::string superclass_method_name (void); + std::string superclass_package_name (void); + std::string superclass_class_name (void); - symbol_table::symbol_record *meta_class_rec (void); - symbol_table::symbol_record *meta_package_rec (void); + std::string meta_package_name (void); + std::string meta_class_name (void); std::string text_rep (void); @@ -137,14 +136,14 @@ symbol_table::symbol_record *sr; struct { - symbol_table::symbol_record *mr; - symbol_table::symbol_record *cr; - symbol_table::symbol_record *pr; + std::string *method_nm; + std::string *package_nm; + std::string *class_nm; } sc; struct { - symbol_table::symbol_record *cr; - symbol_table::symbol_record *pr; + std::string *package_nm; + std::string *class_nm; } mc; }; std::string orig_text; diff -r e42d4f152766 -r 8f256148d82b liboctave/array/Array.cc --- a/liboctave/array/Array.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/liboctave/array/Array.cc Tue Jan 07 16:07:54 2014 -0500 @@ -688,9 +688,9 @@ } else { - octave_idx_type sd = sext[lev-1]; - octave_idx_type dd = dext[lev-1]; - octave_idx_type k; + octave_idx_type sd, dd, k; + sd = sext[lev-1]; + dd = dext[lev-1]; for (k = 0; k < cext[lev]; k++) do_resize_fill (src + k * sd, dest + k * dd, rfv, lev - 1); @@ -2571,9 +2571,8 @@ d.xelem (i) = elem (i, i); } } - else - (*current_liboctave_error_handler) - ("diag: requested diagonal out of range"); + else // Matlab returns [] 0x1 for out-of-range diagonal + d.resize (dim_vector (0, 1)); } else { diff -r e42d4f152766 -r 8f256148d82b liboctave/array/CSparse.cc --- a/liboctave/array/CSparse.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/liboctave/array/CSparse.cc Tue Jan 07 16:07:54 2014 -0500 @@ -7688,87 +7688,85 @@ { SparseComplexMatrix r; - if ((a.rows () == b.rows ()) && (a.cols () == b.cols ())) + octave_idx_type a_nr = a.rows (); + octave_idx_type a_nc = a.cols (); + octave_idx_type b_nr = b.rows (); + octave_idx_type b_nc = b.cols (); + + if (a_nr == b_nr && a_nc == b_nc) { - octave_idx_type a_nr = a.rows (); - octave_idx_type a_nc = a.cols (); - - octave_idx_type b_nr = b.rows (); - octave_idx_type b_nc = b.cols (); - - if (a_nr == 0 || b_nc == 0 || a.nnz () == 0 || b.nnz () == 0) - return SparseComplexMatrix (a_nr, a_nc); - - if (a_nr != b_nr || a_nc != b_nc) - gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); - else + r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); + + octave_idx_type jx = 0; + r.cidx (0) = 0; + for (octave_idx_type i = 0 ; i < a_nc ; i++) { - r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); - - octave_idx_type jx = 0; - r.cidx (0) = 0; - for (octave_idx_type i = 0 ; i < a_nc ; i++) - { - octave_idx_type ja = a.cidx (i); - octave_idx_type ja_max = a.cidx (i+1); - bool ja_lt_max= ja < ja_max; - - octave_idx_type jb = b.cidx (i); - octave_idx_type jb_max = b.cidx (i+1); - bool jb_lt_max = jb < jb_max; - - while (ja_lt_max || jb_lt_max ) - { - octave_quit (); - if ((! jb_lt_max) || - (ja_lt_max && (a.ridx (ja) < b.ridx (jb)))) + octave_idx_type ja = a.cidx (i); + octave_idx_type ja_max = a.cidx (i+1); + bool ja_lt_max= ja < ja_max; + + octave_idx_type jb = b.cidx (i); + octave_idx_type jb_max = b.cidx (i+1); + bool jb_lt_max = jb < jb_max; + + while (ja_lt_max || jb_lt_max ) + { + octave_quit (); + if ((! jb_lt_max) || + (ja_lt_max && (a.ridx (ja) < b.ridx (jb)))) + { + Complex tmp = xmin (a.data (ja), 0.); + if (tmp != 0.) { - Complex tmp = xmin (a.data (ja), 0.); - if (tmp != 0.) - { - r.ridx (jx) = a.ridx (ja); - r.data (jx) = tmp; - jx++; - } - ja++; - ja_lt_max= ja < ja_max; + r.ridx (jx) = a.ridx (ja); + r.data (jx) = tmp; + jx++; } - else if (( !ja_lt_max ) || - (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) ) + ja++; + ja_lt_max= ja < ja_max; + } + else if (( !ja_lt_max ) || + (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) ) + { + Complex tmp = xmin (0., b.data (jb)); + if (tmp != 0.) { - Complex tmp = xmin (0., b.data (jb)); - if (tmp != 0.) - { - r.ridx (jx) = b.ridx (jb); - r.data (jx) = tmp; - jx++; - } - jb++; - jb_lt_max= jb < jb_max; + r.ridx (jx) = b.ridx (jb); + r.data (jx) = tmp; + jx++; } - else + jb++; + jb_lt_max= jb < jb_max; + } + else + { + Complex tmp = xmin (a.data (ja), b.data (jb)); + if (tmp != 0.) { - Complex tmp = xmin (a.data (ja), b.data (jb)); - if (tmp != 0.) - { - r.data (jx) = tmp; - r.ridx (jx) = a.ridx (ja); - jx++; - } - ja++; - ja_lt_max= ja < ja_max; - jb++; - jb_lt_max= jb < jb_max; + r.data (jx) = tmp; + r.ridx (jx) = a.ridx (ja); + jx++; } - } - r.cidx (i+1) = jx; - } - - r.maybe_compress (); + ja++; + ja_lt_max= ja < ja_max; + jb++; + jb_lt_max= jb < jb_max; + } + } + r.cidx (i+1) = jx; } + + r.maybe_compress (); } else - (*current_liboctave_error_handler) ("matrix size mismatch"); + { + if (a_nr == 0 || a_nc == 0) + r.resize (a_nr, a_nc); + else if (b_nr == 0 || b_nc == 0) + r.resize (b_nr, b_nc); + else + gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); + } return r; } @@ -7808,91 +7806,85 @@ { SparseComplexMatrix r; - if ((a.rows () == b.rows ()) && (a.cols () == b.cols ())) + octave_idx_type a_nr = a.rows (); + octave_idx_type a_nc = a.cols (); + octave_idx_type b_nr = b.rows (); + octave_idx_type b_nc = b.cols (); + + if (a_nr == b_nr && a_nc == b_nc) { - octave_idx_type a_nr = a.rows (); - octave_idx_type a_nc = a.cols (); - - octave_idx_type b_nr = b.rows (); - octave_idx_type b_nc = b.cols (); - - if (a_nr == 0 || b_nc == 0) - return SparseComplexMatrix (a_nr, a_nc); - if (a.nnz () == 0) - return SparseComplexMatrix (b); - if (b.nnz () == 0) - return SparseComplexMatrix (a); - - if (a_nr != b_nr || a_nc != b_nc) - gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); - else + r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); + + octave_idx_type jx = 0; + r.cidx (0) = 0; + for (octave_idx_type i = 0 ; i < a_nc ; i++) { - r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); - - octave_idx_type jx = 0; - r.cidx (0) = 0; - for (octave_idx_type i = 0 ; i < a_nc ; i++) - { - octave_idx_type ja = a.cidx (i); - octave_idx_type ja_max = a.cidx (i+1); - bool ja_lt_max= ja < ja_max; - - octave_idx_type jb = b.cidx (i); - octave_idx_type jb_max = b.cidx (i+1); - bool jb_lt_max = jb < jb_max; - - while (ja_lt_max || jb_lt_max ) - { - octave_quit (); - if ((! jb_lt_max) || - (ja_lt_max && (a.ridx (ja) < b.ridx (jb)))) + octave_idx_type ja = a.cidx (i); + octave_idx_type ja_max = a.cidx (i+1); + bool ja_lt_max= ja < ja_max; + + octave_idx_type jb = b.cidx (i); + octave_idx_type jb_max = b.cidx (i+1); + bool jb_lt_max = jb < jb_max; + + while (ja_lt_max || jb_lt_max ) + { + octave_quit (); + if ((! jb_lt_max) || + (ja_lt_max && (a.ridx (ja) < b.ridx (jb)))) + { + Complex tmp = xmax (a.data (ja), 0.); + if (tmp != 0.) { - Complex tmp = xmax (a.data (ja), 0.); - if (tmp != 0.) - { - r.ridx (jx) = a.ridx (ja); - r.data (jx) = tmp; - jx++; - } - ja++; - ja_lt_max= ja < ja_max; + r.ridx (jx) = a.ridx (ja); + r.data (jx) = tmp; + jx++; } - else if (( !ja_lt_max ) || - (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) ) + ja++; + ja_lt_max= ja < ja_max; + } + else if (( !ja_lt_max ) || + (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) ) + { + Complex tmp = xmax (0., b.data (jb)); + if (tmp != 0.) { - Complex tmp = xmax (0., b.data (jb)); - if (tmp != 0.) - { - r.ridx (jx) = b.ridx (jb); - r.data (jx) = tmp; - jx++; - } - jb++; - jb_lt_max= jb < jb_max; + r.ridx (jx) = b.ridx (jb); + r.data (jx) = tmp; + jx++; } - else + jb++; + jb_lt_max= jb < jb_max; + } + else + { + Complex tmp = xmax (a.data (ja), b.data (jb)); + if (tmp != 0.) { - Complex tmp = xmax (a.data (ja), b.data (jb)); - if (tmp != 0.) - { - r.data (jx) = tmp; - r.ridx (jx) = a.ridx (ja); - jx++; - } - ja++; - ja_lt_max= ja < ja_max; - jb++; - jb_lt_max= jb < jb_max; + r.data (jx) = tmp; + r.ridx (jx) = a.ridx (ja); + jx++; } - } - r.cidx (i+1) = jx; - } - - r.maybe_compress (); + ja++; + ja_lt_max= ja < ja_max; + jb++; + jb_lt_max= jb < jb_max; + } + } + r.cidx (i+1) = jx; } + + r.maybe_compress (); } else - (*current_liboctave_error_handler) ("matrix size mismatch"); + { + if (a_nr == 0 || a_nc == 0) + r.resize (a_nr, a_nc); + else if (b_nr == 0 || b_nc == 0) + r.resize (b_nr, b_nc); + else + gripe_nonconformant ("max", a_nr, a_nc, b_nr, b_nc); + } return r; } diff -r e42d4f152766 -r 8f256148d82b liboctave/array/DiagArray2.cc --- a/liboctave/array/DiagArray2.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/liboctave/array/DiagArray2.cc Tue Jan 07 16:07:54 2014 -0500 @@ -66,9 +66,8 @@ d = Array (dim_vector (std::min (cols () - k, rows ()), 1), T ()); else if (k < 0 && -k < rows ()) d = Array (dim_vector (std::min (rows () + k, cols ()), 1), T ()); - else - (*current_liboctave_error_handler) - ("diag: requested diagonal out of range"); + else // Matlab returns [] 0x1 for out-of-range diagonal + d.resize (dim_vector (0, 1)); return d; } diff -r e42d4f152766 -r 8f256148d82b liboctave/array/Sparse.cc --- a/liboctave/array/Sparse.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/liboctave/array/Sparse.cc Tue Jan 07 16:07:54 2014 -0500 @@ -2490,9 +2490,8 @@ } } } - else - (*current_liboctave_error_handler) - ("diag: requested diagonal out of range"); + else // Matlab returns [] 0x1 for out-of-range diagonal + d = Sparse (0, 1, 0); } else if (nnr != 0 && nnc != 0) { diff -r e42d4f152766 -r 8f256148d82b liboctave/array/dSparse.cc --- a/liboctave/array/dSparse.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/liboctave/array/dSparse.cc Tue Jan 07 16:07:54 2014 -0500 @@ -7801,84 +7801,85 @@ { SparseMatrix r; - if ((a.rows () == b.rows ()) && (a.cols () == b.cols ())) + octave_idx_type a_nr = a.rows (); + octave_idx_type a_nc = a.cols (); + octave_idx_type b_nr = b.rows (); + octave_idx_type b_nc = b.cols (); + + if (a_nr == b_nr && a_nc == b_nc) { - octave_idx_type a_nr = a.rows (); - octave_idx_type a_nc = a.cols (); - - octave_idx_type b_nr = b.rows (); - octave_idx_type b_nc = b.cols (); - - if (a_nr != b_nr || a_nc != b_nc) - gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); - else + r = SparseMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); + + octave_idx_type jx = 0; + r.cidx (0) = 0; + for (octave_idx_type i = 0 ; i < a_nc ; i++) { - r = SparseMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); - - octave_idx_type jx = 0; - r.cidx (0) = 0; - for (octave_idx_type i = 0 ; i < a_nc ; i++) - { - octave_idx_type ja = a.cidx (i); - octave_idx_type ja_max = a.cidx (i+1); - bool ja_lt_max= ja < ja_max; - - octave_idx_type jb = b.cidx (i); - octave_idx_type jb_max = b.cidx (i+1); - bool jb_lt_max = jb < jb_max; - - while (ja_lt_max || jb_lt_max ) - { - octave_quit (); - if ((! jb_lt_max) || - (ja_lt_max && (a.ridx (ja) < b.ridx (jb)))) + octave_idx_type ja = a.cidx (i); + octave_idx_type ja_max = a.cidx (i+1); + bool ja_lt_max= ja < ja_max; + + octave_idx_type jb = b.cidx (i); + octave_idx_type jb_max = b.cidx (i+1); + bool jb_lt_max = jb < jb_max; + + while (ja_lt_max || jb_lt_max ) + { + octave_quit (); + if ((! jb_lt_max) || + (ja_lt_max && (a.ridx (ja) < b.ridx (jb)))) + { + double tmp = xmin (a.data (ja), 0.); + if (tmp != 0.) { - double tmp = xmin (a.data (ja), 0.); - if (tmp != 0.) - { - r.ridx (jx) = a.ridx (ja); - r.data (jx) = tmp; - jx++; - } - ja++; - ja_lt_max= ja < ja_max; + r.ridx (jx) = a.ridx (ja); + r.data (jx) = tmp; + jx++; } - else if (( !ja_lt_max ) || - (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) ) + ja++; + ja_lt_max= ja < ja_max; + } + else if (( !ja_lt_max ) || + (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) ) + { + double tmp = xmin (0., b.data (jb)); + if (tmp != 0.) { - double tmp = xmin (0., b.data (jb)); - if (tmp != 0.) - { - r.ridx (jx) = b.ridx (jb); - r.data (jx) = tmp; - jx++; - } - jb++; - jb_lt_max= jb < jb_max; + r.ridx (jx) = b.ridx (jb); + r.data (jx) = tmp; + jx++; } - else + jb++; + jb_lt_max= jb < jb_max; + } + else + { + double tmp = xmin (a.data (ja), b.data (jb)); + if (tmp != 0.) { - double tmp = xmin (a.data (ja), b.data (jb)); - if (tmp != 0.) - { - r.data (jx) = tmp; - r.ridx (jx) = a.ridx (ja); - jx++; - } - ja++; - ja_lt_max= ja < ja_max; - jb++; - jb_lt_max= jb < jb_max; + r.data (jx) = tmp; + r.ridx (jx) = a.ridx (ja); + jx++; } - } - r.cidx (i+1) = jx; - } - - r.maybe_compress (); + ja++; + ja_lt_max= ja < ja_max; + jb++; + jb_lt_max= jb < jb_max; + } + } + r.cidx (i+1) = jx; } + + r.maybe_compress (); } else - (*current_liboctave_error_handler) ("matrix size mismatch"); + { + if (a_nr == 0 || a_nc == 0) + r.resize (a_nr, a_nc); + else if (b_nr == 0 || b_nc == 0) + r.resize (b_nr, b_nc); + else + gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); + } return r; } @@ -7951,84 +7952,85 @@ { SparseMatrix r; - if ((a.rows () == b.rows ()) && (a.cols () == b.cols ())) + octave_idx_type a_nr = a.rows (); + octave_idx_type a_nc = a.cols (); + octave_idx_type b_nr = b.rows (); + octave_idx_type b_nc = b.cols (); + + if (a_nr == b_nr && a_nc == b_nc) { - octave_idx_type a_nr = a.rows (); - octave_idx_type a_nc = a.cols (); - - octave_idx_type b_nr = b.rows (); - octave_idx_type b_nc = b.cols (); - - if (a_nr != b_nr || a_nc != b_nc) - gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); - else + r = SparseMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); + + octave_idx_type jx = 0; + r.cidx (0) = 0; + for (octave_idx_type i = 0 ; i < a_nc ; i++) { - r = SparseMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); - - octave_idx_type jx = 0; - r.cidx (0) = 0; - for (octave_idx_type i = 0 ; i < a_nc ; i++) - { - octave_idx_type ja = a.cidx (i); - octave_idx_type ja_max = a.cidx (i+1); - bool ja_lt_max= ja < ja_max; - - octave_idx_type jb = b.cidx (i); - octave_idx_type jb_max = b.cidx (i+1); - bool jb_lt_max = jb < jb_max; - - while (ja_lt_max || jb_lt_max ) - { - octave_quit (); - if ((! jb_lt_max) || - (ja_lt_max && (a.ridx (ja) < b.ridx (jb)))) + octave_idx_type ja = a.cidx (i); + octave_idx_type ja_max = a.cidx (i+1); + bool ja_lt_max= ja < ja_max; + + octave_idx_type jb = b.cidx (i); + octave_idx_type jb_max = b.cidx (i+1); + bool jb_lt_max = jb < jb_max; + + while (ja_lt_max || jb_lt_max ) + { + octave_quit (); + if ((! jb_lt_max) || + (ja_lt_max && (a.ridx (ja) < b.ridx (jb)))) + { + double tmp = xmax (a.data (ja), 0.); + if (tmp != 0.) { - double tmp = xmax (a.data (ja), 0.); - if (tmp != 0.) - { - r.ridx (jx) = a.ridx (ja); - r.data (jx) = tmp; - jx++; - } - ja++; - ja_lt_max= ja < ja_max; + r.ridx (jx) = a.ridx (ja); + r.data (jx) = tmp; + jx++; } - else if (( !ja_lt_max ) || - (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) ) + ja++; + ja_lt_max= ja < ja_max; + } + else if (( !ja_lt_max ) || + (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) ) + { + double tmp = xmax (0., b.data (jb)); + if (tmp != 0.) { - double tmp = xmax (0., b.data (jb)); - if (tmp != 0.) - { - r.ridx (jx) = b.ridx (jb); - r.data (jx) = tmp; - jx++; - } - jb++; - jb_lt_max= jb < jb_max; + r.ridx (jx) = b.ridx (jb); + r.data (jx) = tmp; + jx++; } - else + jb++; + jb_lt_max= jb < jb_max; + } + else + { + double tmp = xmax (a.data (ja), b.data (jb)); + if (tmp != 0.) { - double tmp = xmax (a.data (ja), b.data (jb)); - if (tmp != 0.) - { - r.data (jx) = tmp; - r.ridx (jx) = a.ridx (ja); - jx++; - } - ja++; - ja_lt_max= ja < ja_max; - jb++; - jb_lt_max= jb < jb_max; + r.data (jx) = tmp; + r.ridx (jx) = a.ridx (ja); + jx++; } - } - r.cidx (i+1) = jx; - } - - r.maybe_compress (); + ja++; + ja_lt_max= ja < ja_max; + jb++; + jb_lt_max= jb < jb_max; + } + } + r.cidx (i+1) = jx; } + + r.maybe_compress (); } else - (*current_liboctave_error_handler) ("matrix size mismatch"); + { + if (a_nr == 0 || a_nc == 0) + r.resize (a_nr, a_nc); + else if (b_nr == 0 || b_nc == 0) + r.resize (b_nr, b_nc); + else + gripe_nonconformant ("max", a_nr, a_nc, b_nr, b_nc); + } return r; } diff -r e42d4f152766 -r 8f256148d82b liboctave/operators/mx-inlines.cc --- a/liboctave/operators/mx-inlines.cc Tue Jan 07 16:07:21 2014 -0500 +++ b/liboctave/operators/mx-inlines.cc Tue Jan 07 16:07:54 2014 -0500 @@ -1345,8 +1345,8 @@ inline T mx_inline_xsum (const T *v, octave_idx_type n) { - T s = 0; - T e = 0; + T s, e; + s = e = 0; for (octave_idx_type i = 0; i < n; i++) twosum_accum (s, e, v[i]); diff -r e42d4f152766 -r 8f256148d82b liboctave/util/base-list.h --- a/liboctave/util/base-list.h Tue Jan 07 16:07:21 2014 -0500 +++ b/liboctave/util/base-list.h Tue Jan 07 16:07:54 2014 -0500 @@ -104,8 +104,6 @@ // For backward compatibility. void append (const elt_type& s) { lst.push_back (s); } -protected: - octave_base_list (void) : lst () { } octave_base_list (const std::list& l) : lst (l) { } diff -r e42d4f152766 -r 8f256148d82b scripts/deprecated/default_save_options.m --- a/scripts/deprecated/default_save_options.m Tue Jan 07 16:07:21 2014 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -## Copyright (C) 2013 Rik Wehbring -## -## 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 -## . - -## -*- texinfo -*- -## @deftypefn {Built-in Function} {@var{val} =} default_save_options () -## @deftypefnx {Built-in Function} {@var{old_val} =} default_save_options (@var{new_val}) -## @deftypefnx {Built-in Function} {} default_save_options (@var{new_val}, "local") -## This function has been deprecated. Use @code{@file{save_default_options}} -## instead. -## @seealso{save_default_options} -## @end deftypefn - -## Deprecated in 3.8 - -function retval = default_save_options (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "default_save_options is obsolete and will be removed from a future version of Octave, please use save_default_options instead"); - endif - - retval = save_default_options (varargin{:}); - -endfunction - diff -r e42d4f152766 -r 8f256148d82b scripts/deprecated/find_dir_in_path.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/deprecated/find_dir_in_path.m Tue Jan 07 16:07:54 2014 -0500 @@ -0,0 +1,40 @@ +## Copyright (C) 2013 John W. Eaton +## +## 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 +## . + +## -*- texinfo -*- +## @deftypefn {Built-in Function} {} find_dir_in_path (@var{dir}) +## @deftypefnx {Built-in Function} {} find_dir_in_path (@var{dir}, "all") +## This function has been deprecated. Use @code{dir_in_loadpath} instead. +## @seealso{dir_in_loadpath} +## @end deftypefn + +## Deprecated in version 4.2 + +function retval = find_dir_in_path (varargin) + + persistent warned = false; + if (! warned) + warned = true; + warning ("Octave:deprecated-function", + "find_dir_in_path is obsolete and will be removed from a future version of Octave, please use dir_in_loadpath instead"); + endif + + retval = dir_in_loadpath (varargin{:}); + +endfunction + diff -r e42d4f152766 -r 8f256148d82b scripts/deprecated/gen_doc_cache.m --- a/scripts/deprecated/gen_doc_cache.m Tue Jan 07 16:07:21 2014 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -## Copyright (C) 2013 Rik Wehbring -## -## 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 -## . - -## -*- texinfo -*- -## @deftypefn {Function File} {} gen_doc_cache (@var{out_file}, @var{directory}) -## This function has been deprecated. Use @code{doc_cache_create} instead. -## @seealso{doc_cache_create} -## @end deftypefn - -## Deprecated in 3.8 - -function gen_doc_cache (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "gen_doc_cache is obsolete and will be removed from a future version of Octave, please use doc_cache_create instead"); - endif - - doc_cache_create (varargin{:}); - -endfunction - diff -r e42d4f152766 -r 8f256148d82b scripts/deprecated/interp1q.m --- a/scripts/deprecated/interp1q.m Tue Jan 07 16:07:21 2014 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -## Copyright (C) 2008-2013 David Bateman -## -## 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 -## . - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{yi} =} interp1q (@var{x}, @var{y}, @var{xi}) -## One-dimensional linear interpolation without error checking. -## Interpolates @var{y}, defined at the points @var{x}, at the points -## @var{xi}. The sample points @var{x} must be a strictly monotonically -## increasing column vector. If @var{y} is a matrix or an N-dimensional -## array, the interpolation is performed on each column of @var{y}. If -## @var{y} is a vector, it must be a column vector of the same length as -## @var{x}. -## -## Values of @var{xi} beyond the endpoints of the interpolation result -## in NA being returned. -## -## Note that the error checking is only a significant portion of the -## execution time of this @code{interp1} if the size of the input arguments -## is relatively small. Therefore, the benefit of using @code{interp1q} -## is relatively small. -## @seealso{interp1} -## @end deftypefn - -function yi = interp1q (x, y, xi) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "interp1q is obsolete and will be removed from a future version of Octave; use interp1 instead"); - endif - - x = x(:); - nx = rows (x); - szy = size (y); - y = y(:,:); - [ny, nc] = size (y); - szx = size (xi); - xi = xi (:); - dy = diff (y); - dx = diff (x); - idx = lookup (x, xi, "lr"); - s = (xi - x (idx)) ./ dx (idx); - yi = bsxfun (@times, s, dy(idx,:)) + y(idx,:); - range = xi < x(1) | !(xi <= x(nx)); - yi(range,:) = NA; - if (length (szx) == 2 && any (szx == 1)) - yi = reshape (yi, [max(szx), szy(2:end)]); - else - yi = reshape (yi, [szx, szy(2:end)]); - endif -endfunction - - -%!shared xp, yp, xi, yi -%! xp = [0:2:10].'; yp = sin (2*pi*xp/5); -%! xi = [-1; 0; 2.2; 4; 6.6; 10; 11]; -%! yi = interp1 (xp,yp,xi); -%!assert (interp1q (xp,yp, [min(xp)-1; max(xp)+1]), [NA; NA]); -%!assert (interp1q (xp,yp,xp), yp, 100*eps); -%!assert (isempty (interp1q (xp,yp,[]))); -%!assert (interp1q (xp,yp,xi), yi); -%!assert (interp1q (xp,[yp,yp],xi), [yi, yi]); -%!assert (interp1q (xp,yp,[xi,xi]), [yi, yi]); -%!assert (interp1q (xp,[yp,yp],[xi,xi]), cat (3, [yi, yi], [yi, yi])); - diff -r e42d4f152766 -r 8f256148d82b scripts/deprecated/isequalwithequalnans.m --- a/scripts/deprecated/isequalwithequalnans.m Tue Jan 07 16:07:21 2014 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -## Copyright (C) 2005-2013 William Poetra Yoga Hadisoeseno -## -## 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 -## . - -## -*- texinfo -*- -## @deftypefn {Function File} {} isequalwithequalnans (@var{x1}, @var{x2}, @dots{}) -## This function has been deprecated. Use @code{@file{isequaln}} instead. -## @seealso{isequaln} -## @end deftypefn - -## Deprecated in 3.8 - -function retval = isequalwithequalnans (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "isequalwithequalnans is obsolete and will be removed from a future version of Octave, please use isequaln instead"); - endif - - retval = isequaln (varargin{:}); - -endfunction - - -## test for equality -%!assert (isequalwithequalnans ({1,2,NaN,4},{1,2,NaN,4}), true) -%!assert (isequalwithequalnans ([1,2,NaN,4],[1,2,NaN,4]), true) -## test for inequality -%!assert (isequalwithequalnans ([1,2,NaN,4],[1,NaN,3,4]), false) -%!assert (isequalwithequalnans ([1,2,NaN,4],[1,2,3,4]), false) -## test for equality (struct) -%!assert (isequalwithequalnans (struct ('a',NaN,'b',2),struct ('a',NaN,'b',2),struct ('a',NaN,'b',2)), true) -%!assert (isequalwithequalnans (1,2,1), false) - diff -r e42d4f152766 -r 8f256148d82b scripts/deprecated/java_convert_matrix.m --- a/scripts/deprecated/java_convert_matrix.m Tue Jan 07 16:07:21 2014 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -## Copyright (C) 2012-2013 Rik Wehbring -## -## 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 -## . - -## -*- texinfo -*- -## @deftypefn {Built-in Function} {@var{val} =} java_convert_matrix () -## @deftypefnx {Built-in Function} {@var{old_val} =} java_convert_matrix (@var{new_val}) -## @deftypefnx {Built-in Function} {} java_convert_matrix (@var{new_val}, "local") -## Query or set the internal variable that controls whether Java arrays are -## automatically converted to Octave matrices. The default value is false. -## -## When called from inside a function with the @qcode{"local"} option, the -## variable is changed locally for the function and any subroutines it calls. -## The original variable value is restored when exiting the function. -## @seealso{java_matrix_autoconversion, java_unsigned_conversion, java_debug} -## @end deftypefn - -function old_val = java_convert_matrix (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "java_convert_matrix is obsolete and will be removed from a future version of Octave; use java_matrix_autoconversion instead"); - endif - - if (nargin > 2) - print_usage (); - endif - - old_val = java_matrix_autoconversion (varargin{:}); - -endfunction - diff -r e42d4f152766 -r 8f256148d82b scripts/deprecated/java_debug.m --- a/scripts/deprecated/java_debug.m Tue Jan 07 16:07:21 2014 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -## Copyright (C) 2012-2013 Rik Wehbring -## -## 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 -## . - -## -*- texinfo -*- -## @deftypefn {Built-in Function} {@var{val} =} java_debug () -## @deftypefnx {Built-in Function} {@var{old_val} =} java_debug (@var{new_val}) -## @deftypefnx {Built-in Function} {} java_debug (@var{new_val}, "local") -## Query or set the internal variable that determines whether extra debugging -## information regarding the initialization of the JVM and any Java exceptions -## is printed. -## -## When called from inside a function with the @qcode{"local"} option, the -## variable is changed locally for the function and any subroutines it calls. -## The original variable value is restored when exiting the function. -## @seealso{debug_java, java_convert_matrix, java_unsigned_conversion} -## @end deftypefn - -function old_val = java_debug (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "java_debug is obsolete and will be removed from a future version of Octave; use debug_java instead"); - endif - - if (nargin > 2) - print_usage (); - endif - - old_val = debug_java (varargin{:}); - -endfunction - diff -r e42d4f152766 -r 8f256148d82b scripts/deprecated/java_get.m --- a/scripts/deprecated/java_get.m Tue Jan 07 16:07:21 2014 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -## Copyright (C) 2012-2013 Rik Wehbring -## -## 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 -## . - -## -*- texinfo -*- -## @deftypefn {Loadable Function} {@var{val} =} java_get (@var{obj}, @var{name}) -## Get the value of the field @var{name} of the Java object @var{obj}. For -## static fields, @var{obj} can be a string representing the fully qualified -## name of the corresponding class. -## -## When @var{obj} is a regular Java object, structure-like indexing can be -## used as a shortcut syntax. For instance, the two following statements are -## equivalent -## -## @example -## @group -## java_get (x, "field1") -## x.field1 -## @end group -## @end example -## -## @seealso{java_set, javaMethod, javaObject} -## @end deftypefn - -function retval = java_get (obj, name) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "java_get is obsolete and will be removed from a future version of Octave; use structure-like indexing instead"); - endif - - if (nargin != 2) - print_usage (); - endif - - if (isjava (obj)) - retval = obj.(name); - elseif (ischar (obj)) - ## FIXME: Need a solution for getting static fields of class - ## which does not depend on __java_get__ which will be removed. - retval = __java_get__ (obj, name); - else - error ("java_get: OBJ must be a Java object"); - endif - -endfunction - diff -r e42d4f152766 -r 8f256148d82b scripts/deprecated/java_invoke.m --- a/scripts/deprecated/java_invoke.m Tue Jan 07 16:07:21 2014 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -## Copyright (C) 2007, 2013 Michael Goffioul -## -## 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 -## . - -## -*- texinfo -*- -## @deftypefn {Built-in Function} {@var{ret} =} java_invoke (@var{obj}, @var{methodname}) -## @deftypefnx {Built-in Function} {@var{ret} =} java_invoke (@var{obj}, @var{methodname}, @var{arg1}, @dots{}) -## Invoke the method @var{methodname} on the Java object @var{obj} with the -## arguments @var{arg1}, @dots{} For static methods, @var{obj} can be a -## string representing the fully qualified name of the corresponding class. -## The function returns the result of the method invocation. -## -## When @var{obj} is a regular Java object, structure-like indexing can be -## used as a shortcut syntax. For instance, the two following statements are -## equivalent -## -## @example -## @group -## ret = java_invoke (x, "method1", 1.0, "a string") -## ret = x.method1 (1.0, "a string") -## @end group -## @end example -## -## @seealso{javaMethod, javaObject} -## @end deftypefn - -function retval = java_invoke (obj, methodname, varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "java_invoke is obsolete and will be removed from a future version of Octave, please use javaMethod instead"); - endif - - if (nargin < 2) - print_usage (); - endif - - retval = javaMethod (methodname, obj, varargin{:}); - -endfunction - diff -r e42d4f152766 -r 8f256148d82b scripts/deprecated/java_set.m --- a/scripts/deprecated/java_set.m Tue Jan 07 16:07:21 2014 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -## Copyright (C) 2012-2013 Rik Wehbring -## -## 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 -## . - -## -*- texinfo -*- -## @deftypefn {Loadable Function} {@var{obj} =} java_set (@var{obj}, @var{name}, @var{val}) -## Set the value of the field @var{name} of the Java object @var{obj} to -## @var{val}. For static fields, @var{obj} can be a string representing the -## fully qualified named of the corresponding Java class. -## -## When @var{obj} is a regular Java object, structure-like indexing can be -## used as a shortcut syntax. For instance, the two following statements are -## equivalent -## -## @example -## @group -## java_set (x, "field1", val) -## x.field1 = val -## @end group -## @end example -## -## @seealso{java_get, javaMethod, javaObject} -## @end deftypefn - -function retval = java_set (obj, name, val) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "java_set is obsolete and will be removed from a future version of Octave; use structure-like indexing instead"); - endif - - if (nargin != 3) - print_usage (); - endif - - if (isjava (obj)) - obj.(name) = val; - elseif (ischar (obj)) - ## FIXME: Need a solution for getting static fields of class - ## which does not depend on __java_set__ which will be removed. - retval = __java_set__ (obj, name, val); - else - error ("java_set: OBJ must be a Java object"); - endif - -endfunction - diff -r e42d4f152766 -r 8f256148d82b scripts/deprecated/java_unsigned_conversion.m --- a/scripts/deprecated/java_unsigned_conversion.m Tue Jan 07 16:07:21 2014 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -## Copyright (C) 2012-2013 Rik Wehbring -## -## 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 -## . - -## -*- texinfo -*- -## @deftypefn {Built-in Function} {@var{val} =} java_unsigned_conversion () -## @deftypefnx {Built-in Function} {@var{old_val} =} java_unsigned_conversion (@var{new_val}) -## @deftypefnx {Built-in Function} {} java_unsigned_conversion (@var{new_val}, "local") -## Query or set the internal variable that controls how integer classes are -## converted when Java matrix autoconversion is enabled. When enabled, Java -## arrays of class Byte or Integer are converted to matrices of class uint8 or -## uint32 respectively. -## -## When called from inside a function with the @qcode{"local"} option, the -## variable is changed locally for the function and any subroutines it calls. -## The original variable value is restored when exiting the function. -## @seealso{java_unsigned_autoconversion, java_convert_matrix, debug_java} -## @end deftypefn - -function old_val = java_unsigned_conversion (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "java_unsigned_conversion is obsolete and will be removed from a future version of Octave; use java_unsigned_autoconversion instead"); - endif - - if (nargin > 2) - print_usage (); - endif - - old_val = java_unsigned_autoconversion (varargin{:}); - -endfunction - diff -r e42d4f152766 -r 8f256148d82b scripts/deprecated/javafields.m --- a/scripts/deprecated/javafields.m Tue Jan 07 16:07:21 2014 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -## Copyright (C) 2007, 2013 Michael Goffioul -## -## 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 -## . - -## -*- texinfo -*- -## @deftypefn {Function File} {} javafields (@var{javaobj}) -## @deftypefnx {Function File} {} javafields ("@var{classname}") -## @deftypefnx {Function File} {@var{fld_names} =} javafields (@dots{}) -## Return the fields of a Java object or Java class in the form of a cell -## array of strings. If no output is requested, print the result -## to the standard output. -## @seealso{fieldnames, methods, javaObject} -## @end deftypefn - -function fld_names = javafields (javaobj) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "javafields is obsolete and will be removed from a future version of Octave, please use fieldnames instead"); - endif - - if (nargin != 1) - print_usage (); - endif - - c_methods = javaMethod ("getFields", "org.octave.ClassHelper", javaobj); - method_list = ostrsplit (c_methods, ';'); - - if (nargout == 0) - if (! isempty (method_list)) - disp (method_list); - endif - else - fld_names = cellstr (method_list); - endif - -endfunction - diff -r e42d4f152766 -r 8f256148d82b scripts/deprecated/javamethods.m --- a/scripts/deprecated/javamethods.m Tue Jan 07 16:07:21 2014 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -## Copyright (C) 2007, 2013 Michael Goffioul -## -## 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 -## . - -## -*- texinfo -*- -## @deftypefn {Function File} {} javamethods (@var{javaobj}) -## @deftypefnx {Function File} {} javamethods ("@var{classname}") -## @deftypefnx {Function File} {@var{mtd_names} =} javamethods (@dots{}) -## Return the methods of a Java object or Java class in the form of a cell -## array of strings. If no output is requested, print the result to the -## standard output. -## @seealso{methods, fieldnames, javaMethod, javaObject} -## @end deftypefn - -function mtd_names = javamethods (classname) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "javamethods is obsolete and will be removed from a future version of Octave, please use methods instead"); - endif - - if (nargin != 1) - print_usage (); - endif - - cls_methods = javaMethod ("getMethods", "org.octave.ClassHelper", classname); - method_list = ostrsplit (cls_methods, ';'); - - if (nargout == 0) - if (! isempty (method_list)) - disp (method_list); - endif - else - mtd_names = cellstr (method_list); - endif - -endfunction - diff -r e42d4f152766 -r 8f256148d82b scripts/deprecated/module.mk --- a/scripts/deprecated/module.mk Tue Jan 07 16:07:21 2014 -0500 +++ b/scripts/deprecated/module.mk Tue Jan 07 16:07:54 2014 -0500 @@ -1,23 +1,8 @@ FCN_FILE_DIRS += deprecated deprecated_FCN_FILES = \ - deprecated/default_save_options.m \ - deprecated/gen_doc_cache.m \ - deprecated/interp1q.m \ - deprecated/isequalwithequalnans.m \ - deprecated/isstr.m \ - deprecated/java_convert_matrix.m \ - deprecated/java_debug.m \ - deprecated/java_get.m \ - deprecated/java_invoke.m \ - deprecated/java_new.m \ - deprecated/java_unsigned_conversion.m \ - deprecated/java_set.m \ - deprecated/javafields.m \ - deprecated/javamethods.m \ - deprecated/re_read_readline_init_file.m \ - deprecated/read_readline_init_file.m \ - deprecated/saving_history.m + deprecated/find_dir_in_path.m \ + deprecated/isstr.m FCN_FILES += $(deprecated_FCN_FILES) diff -r e42d4f152766 -r 8f256148d82b scripts/deprecated/re_read_readline_init_file.m --- a/scripts/deprecated/re_read_readline_init_file.m Tue Jan 07 16:07:21 2014 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -## Copyright (C) 2013 Rik Wehbring -## -## 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 -## . - -## -*- texinfo -*- -## @deftypefn {Built-in Function} {} re_read_readline_init_file (@var{file}) -## This function has been deprecated. Use -## @code{@file{readline_re_read_init_file}} instead. -## @seealso{readline_read_init_file} -## @end deftypefn - -## Deprecated in 3.8 - -function re_read_readline_init_file (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "re_read_readline_init_file is obsolete and will be removed from a future version of Octave, please use readline_re_read_init_file instead"); - endif - - readline_re_read_init_file (varargin{:}); - -endfunction - diff -r e42d4f152766 -r 8f256148d82b scripts/deprecated/read_readline_init_file.m --- a/scripts/deprecated/read_readline_init_file.m Tue Jan 07 16:07:21 2014 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -## Copyright (C) 2013 Rik Wehbring -## -## 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 -## . - -## -*- texinfo -*- -## @deftypefn {Built-in Function} {} read_readline_init_file (@var{file}) -## This function has been deprecated. Use -## @code{@file{readline_read_init_file}} instead. -## @seealso{readline_read_init_file} -## @end deftypefn - -## Deprecated in 3.8 - -function read_readline_init_file (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "read_readline_init_file is obsolete and will be removed from a future version of Octave, please use readline_read_init_file instead"); - endif - - readline_read_init_file (varargin{:}); - -endfunction - diff -r e42d4f152766 -r 8f256148d82b scripts/deprecated/saving_history.m --- a/scripts/deprecated/saving_history.m Tue Jan 07 16:07:21 2014 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -## Copyright (C) 2013 Rik Wehbring -## -## 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 -## . - -## -*- texinfo -*- -## @deftypefn {Built-in Function} {@var{val} =} saving_history () -## @deftypefnx {Built-in Function} {@var{old_val} =} saving_history (@var{new_val}) -## @deftypefnx {Built-in Function} {} saving_history (@var{new_val}, "local") -## This function has been deprecated. Use @code{@file{history_save}} instead. -## @seealso{history_save} -## @end deftypefn - -## Deprecated in 3.8 - -function retval = saving_history (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "saving_history is obsolete and will be removed from a future version of Octave, please use history_save instead"); - endif - - retval = save_default_options (varargin{:}); - -endfunction - diff -r e42d4f152766 -r 8f256148d82b scripts/general/bincoeff.m diff -r e42d4f152766 -r 8f256148d82b scripts/general/cell2mat.m --- a/scripts/general/cell2mat.m Tue Jan 07 16:07:21 2014 -0500 +++ b/scripts/general/cell2mat.m Tue Jan 07 16:07:54 2014 -0500 @@ -32,15 +32,14 @@ print_usage (); endif - if (! iscell (c)) - error ("cell2mat: C is not a cell array"); - endif - nb = numel (c); if (nb == 0) m = []; else + if (! iscell (c)) + error ("cell2mat: C must be a cell array"); + endif ## Check first for valid matrix types valid = cellfun ("isnumeric", c); @@ -94,6 +93,7 @@ %! cell2mat (C) %!assert (cell2mat ({}), []); +%!assert (cell2mat ([]), []); %!test %! C = {[1], [2 3 4]; [5; 9], [6 7 8; 10 11 12]}; %! D = C; D(:,:,2) = C; @@ -115,7 +115,7 @@ %!error cell2mat () %!error cell2mat (1,2) -%!error cell2mat ([1,2]) +%!error cell2mat ([1,2]) %!error cell2mat ({[1], struct()}) %!error cell2mat ({[1], {1}}) %!error cell2mat ({struct(), {1}}) diff -r e42d4f152766 -r 8f256148d82b scripts/geometry/voronoi.m --- a/scripts/geometry/voronoi.m Tue Jan 07 16:07:21 2014 -0500 +++ b/scripts/geometry/voronoi.m Tue Jan 07 16:07:54 2014 -0500 @@ -74,14 +74,13 @@ endif narg = 1; + hax = NaN; if (isscalar (varargin{1}) && ishandle (varargin{1})) hax = varargin{1}; - if (! isaxes (harg)) - error ("imagesc: HAX argument must be an axes object"); + if (! isaxes (hax)) + error ("voronoi: HAX argument must be an axes object"); endif narg++; - elseif (nargout < 2) - hax = gca (); endif if (nargin < 1 + narg || nargin > 3 + narg) @@ -108,6 +107,8 @@ if (length (x) != length (y)) error ("voronoi: X and Y must be vectors of the same length"); + elseif (length (x) < 2) + error ("voronoi: minimum of 2 points needed"); endif ## Add box to approximate rays to infinity. For Voronoi diagrams the @@ -142,19 +143,35 @@ edges = edges(:, [(edges(1, 1 :end - 1) != edges(1, 2 : end) | ... edges(2, 1 :end - 1) != edges(2, 2 : end)), true]); - ## Eliminate the edges of the diagram representing the box - poutside = (1:rows (p)) ... - (p(:, 1) < xmin - xdelta | p(:, 1) > xmax + xdelta | ... - p(:, 2) < ymin - ydelta | p(:, 2) > ymax + ydelta); - edgeoutside = ismember (edges(1, :), poutside) & ... - ismember (edges(2, :), poutside); - edges(:, edgeoutside) = []; + if (numel (x) > 2) + ## Eliminate the edges of the diagram representing the box + poutside = (1:rows (p)) ... + (p(:, 1) < xmin - xdelta | p(:, 1) > xmax + xdelta | ... + p(:, 2) < ymin - ydelta | p(:, 2) > ymax + ydelta); + edgeoutside = ismember (edges(1, :), poutside) & ... + ismember (edges(2, :), poutside); + edges(:, edgeoutside) = []; + else + ## look for the edge between the two given points + for edge = edges(1:2,:) + if (det ([[[1;1],p(edge,1:2)];1,x(1),y(1)]) + * det ([[[1;1],p(edge,1:2)];1,x(2),y(2)]) < 0) + edges = edge; + break; + endif + endfor + ## Use larger plot limits to make it more likely single bisector is shown. + xdelta = ydelta = max (xdelta, ydelta); + endif ## Get points of the diagram Vvx = reshape (p(edges, 1), size (edges)); Vvy = reshape (p(edges, 2), size (edges)); if (nargout < 2) + if (isnan (hax)) + hax = gca (); + endif h = plot (hax, Vvx, Vvy, linespec{:}, x, y, '+'); lim = [xmin, xmax, ymin, ymax]; axis (lim + 0.1 * [[-1, 1] * xdelta, [-1, 1] * ydelta]); @@ -179,5 +196,18 @@ %! assert (vx(2,:), zeros (1, columns (vx)), eps); %! assert (vy(2,:), zeros (1, columns (vy)), eps); -%% FIXME: Need input validation tests +%!testif HAVE_QHULL +%! ## Special case of just 2 points +%! x = [0 1]; y = [1 0]; +%! [vx, vy] = voronoi (x,y); +%! assert (vx, [-0.7; 1.7], eps); +%! assert (vy, [-0.7; 1.7], eps); +%% Input validation tests +%!error voronoi () +%!error voronoi (ones (3,1)) +%!error voronoi (ones (3,1), ones (3,1), "bogus1", "bogus2", "bogus3") +%!error voronoi (0, ones (3,1), ones (3,1)) +%!error voronoi (ones (3,1), ones (4,1)) +%!error voronoi (2.5, 3.5) + diff -r e42d4f152766 -r 8f256148d82b scripts/gui/errordlg.m diff -r e42d4f152766 -r 8f256148d82b scripts/gui/helpdlg.m diff -r e42d4f152766 -r 8f256148d82b scripts/gui/inputdlg.m diff -r e42d4f152766 -r 8f256148d82b scripts/gui/listdlg.m diff -r e42d4f152766 -r 8f256148d82b scripts/gui/msgbox.m diff -r e42d4f152766 -r 8f256148d82b scripts/gui/private/message_dialog.m diff -r e42d4f152766 -r 8f256148d82b scripts/gui/questdlg.m diff -r e42d4f152766 -r 8f256148d82b scripts/gui/warndlg.m diff -r e42d4f152766 -r 8f256148d82b scripts/help/help.m --- a/scripts/help/help.m Tue Jan 07 16:07:21 2014 -0500 +++ b/scripts/help/help.m Tue Jan 07 16:07:54 2014 -0500 @@ -163,7 +163,7 @@ found = false; - dlist = find_dir_in_path (name, "all"); + dlist = dir_in_loadpath (name, "all"); for i = 1:numel (dlist) fname = make_absolute_filename (fullfile (dlist{i}, "Contents.m")); diff -r e42d4f152766 -r 8f256148d82b scripts/image/private/__imread__.m --- a/scripts/image/private/__imread__.m Tue Jan 07 16:07:21 2014 -0500 +++ b/scripts/image/private/__imread__.m Tue Jan 07 16:07:54 2014 -0500 @@ -90,114 +90,62 @@ endif endif - try - ## Use information from the first image to be read to set defaults. - if (ischar (options.index) && strcmpi (options.index, "all")) - info = __magick_ping__ (fn, 1); - else - info = __magick_ping__ (fn, options.index(1)); - endif + ## Use information from the first image to be read to set defaults. + if (ischar (options.index) && strcmpi (options.index, "all")) + info = __magick_ping__ (fn, 1); + else + info = __magick_ping__ (fn, options.index(1)); + endif - ## Set default for options. - options.region = {1:1:info.rows 1:1:info.columns}; + ## Set default for options. + options.region = {1:1:info.rows 1:1:info.columns}; + + for idx = offset:2:(numel (varargin) - offset + 1) + switch (tolower (varargin{idx})) - for idx = offset:2:(numel (varargin) - offset + 1) - switch (tolower (varargin{idx})) + case {"frames", "index"} + ## Do nothing. This options were already processed before the loop. - case {"frames", "index"} - ## Do nothing. This options were already processed before the loop. - - case "pixelregion", - options.region = varargin{idx+1}; - if (! iscell (options.region) || numel (options.region) != 2) - error ("imread: value for %s must be a 2 element cell array", + case "pixelregion", + options.region = varargin{idx+1}; + if (! iscell (options.region) || numel (options.region) != 2) + error ("imread: value for %s must be a 2 element cell array", + varargin{idx}); + endif + for reg_idx = 1:2 + if (numel (options.region{reg_idx}) == 3) + ## do nothing + elseif (numel (options.region{reg_idx}) == 2) + options.region{reg_idx}(3) = options.region{reg_idx}(2); + options.region{reg_idx}(2) = 1; + else + error ("imread: range for %s must be a 2 or 3 element vector", varargin{idx}); endif - for reg_idx = 1:2 - if (numel (options.region{reg_idx}) == 3) - ## do nothing - elseif (numel (options.region{reg_idx}) == 2) - options.region{reg_idx}(3) = options.region{reg_idx}(2); - options.region{reg_idx}(2) = 1; - else - error ("imread: range for %s must be a 2 or 3 element vector", - varargin{idx}); - endif - options.region{reg_idx} = floor (options.region{reg_idx}(1)): ... - floor (options.region{reg_idx}(2)): ... - floor (options.region{reg_idx}(3)); - endfor - if (options.region{1}(end) > info.rows) - error ("imread: end ROWS for PixelRegions option is larger than image height"); - elseif (options.region{2}(end) > info.columns) - error ("imread: end COLS for PixelRegions option is larger than image width"); - endif - - case "info", - ## We ignore this option. This parameter exists in Matlab to - ## speed up the reading of multipage TIFF by passing a structure - ## that contains information about the start on the file of each - ## page. We can't control it through GraphicsMagic but at least - ## we allow to load multiple pages with one command. - - otherwise - error ("imread: invalid PARAMETER `%s'", varargin{idx}); - - endswitch - endfor - - [varargout{1:nargout}] = __magick_read__ (fn, options); + options.region{reg_idx} = floor (options.region{reg_idx}(1)): ... + floor (options.region{reg_idx}(2)): ... + floor (options.region{reg_idx}(3)); + endfor + if (options.region{1}(end) > info.rows) + error ("imread: end ROWS for PixelRegions option is larger than image height"); + elseif (options.region{2}(end) > info.columns) + error ("imread: end COLS for PixelRegions option is larger than image width"); + endif - catch - ## If we can't read it with Magick, maybe the image is in Octave's - ## native image format. This is from back before Octave had 'imread' - ## and 'imwrite'. Then we had the functions 'loadimage' and 'saveimage'. - ## - ## This "image format" seems to be any file that can be read with - ## load() and contains 2 variables. The variable named "map" is a - ## colormap and must exist whether the image is indexed or not. The - ## other variable must be named "img" or "X" for a "normal" or - ## indexed image. - ## - ## FIXME: this has been deprecated for the next major release (3.8 or 4.0). - ## If someone wants to revive this as yet another image format, a - ## separate Octave package can be written for it, that register the - ## format through imformats. - - magick_error = lasterr (); - - img_field = false; - x_field = false; - map_field = false; + case "info", + ## We ignore this option. This parameter exists in Matlab to + ## speed up the reading of multipage TIFF by passing a structure + ## that contains information about the start on the file of each + ## page. We can't control it through GraphicsMagic but at least + ## we allow to load multiple pages with one command. - try - vars = load (fn); - if (isstruct (vars)) - img_field = isfield (vars, "img"); - x_field = isfield (vars, "X"); - map_field = isfield (vars, "map"); - endif - catch - error ("imread: invalid image file: %s", magick_error); - end_try_catch + otherwise + error ("imread: invalid PARAMETER `%s'", varargin{idx}); - if (map_field && (img_field || x_field)) - varargout{2} = vars.map; - if (img_field) - varargout{1} = vars.img; - else - varargout{1} = vars.X; - endif - persistent warned = false; - if (! warned) - warning ("Octave's native image format has been deprecated."); - warned = true; - endif - else - error ("imread: invalid Octave image file format"); - endif + endswitch + endfor - end_try_catch + [varargout{1:nargout}] = __magick_read__ (fn, options); endfunction @@ -205,10 +153,6 @@ ## can be defined in two places, but only in one place can it also be the ## string "all" function bool = is_valid_index_option (arg) - ## is the index option - bool = false; - if (isvector (arg) && isnumeric (arg) && isreal (arg)) - bool = true; - endif + bool = isvector (arg) && isnumeric (arg) && isreal (arg); endfunction diff -r e42d4f152766 -r 8f256148d82b scripts/miscellaneous/colon.m diff -r e42d4f152766 -r 8f256148d82b scripts/miscellaneous/genvarname.m diff -r e42d4f152766 -r 8f256148d82b scripts/miscellaneous/inputname.m --- a/scripts/miscellaneous/inputname.m Tue Jan 07 16:07:21 2014 -0500 +++ b/scripts/miscellaneous/inputname.m Tue Jan 07 16:07:54 2014 -0500 @@ -57,3 +57,8 @@ %!assert (inputname (1), "hello") %!assert (inputname (2), "worldly") +%!function r = foo (x, y) +%! r = inputname (2); +%!endfunction +%!assert (foo (pi, e), "e"); +%!assert (feval (@foo, pi, e), "e"); diff -r e42d4f152766 -r 8f256148d82b scripts/miscellaneous/ls.m --- a/scripts/miscellaneous/ls.m Tue Jan 07 16:07:21 2014 -0500 +++ b/scripts/miscellaneous/ls.m Tue Jan 07 16:07:54 2014 -0500 @@ -60,7 +60,16 @@ if (nargin > 0) args = tilde_expand (varargin); - if (ispc () && ! isunix ()) + is_dos = (ispc () && ! isunix ()); + if (is_dos) + optsep = "/"; + else + optsep = "-"; + endif + idx = ! strncmp (args, optsep, 1); + ## Enclose paths, potentially having spaces, in double quotes: + args(idx) = strcat ('"', args(idx), '"'); + if (is_dos) ## shell (cmd.exe) on MinGW uses '^' as escape character args = regexprep (args, '([^\w.*? -])', '^$1'); ## Strip UNIX directory character which looks like an option to dir cmd. diff -r e42d4f152766 -r 8f256148d82b scripts/miscellaneous/mex.m --- a/scripts/miscellaneous/mex.m Tue Jan 07 16:07:21 2014 -0500 +++ b/scripts/miscellaneous/mex.m Tue Jan 07 16:07:54 2014 -0500 @@ -23,8 +23,16 @@ ## @seealso{mkoctfile} ## @end deftypefn -function mex (varargin) - args = {"--mex", varargin{:}}; - mkoctfile (args{:}); +function retval = mex (varargin) + + [output, status] = mkoctfile ("--mex", varargin{:}); + + if (! isempty (output)) + disp (output); + endif + if (nargout > 0) + retval = status; + endif + endfunction diff -r e42d4f152766 -r 8f256148d82b scripts/miscellaneous/what.m --- a/scripts/miscellaneous/what.m Tue Jan 07 16:07:21 2014 -0500 +++ b/scripts/miscellaneous/what.m Tue Jan 07 16:07:54 2014 -0500 @@ -37,7 +37,7 @@ if (d(end) == '/' || d(end) == '\') d(end) = []; endif - dtmp = find_dir_in_path (d); + dtmp = dir_in_loadpath (d); if (isempty (dtmp)) error ("what: could not find the directory %s", d); endif diff -r e42d4f152766 -r 8f256148d82b scripts/optimization/fzero.m --- a/scripts/optimization/fzero.m Tue Jan 07 16:07:21 2014 -0500 +++ b/scripts/optimization/fzero.m Tue Jan 07 16:07:54 2014 -0500 @@ -100,7 +100,7 @@ ## Get default options if requested. if (nargin == 1 && ischar (fun) && strcmp (fun, 'defaults')) - x = optimset ("MaxIter", Inf, "MaxFunEvals", Inf, "TolX", 1e-8, + x = optimset ("MaxIter", Inf, "MaxFunEvals", Inf, "TolX", eps, "OutputFcn", [], "FunValCheck", "off"); return; endif @@ -117,7 +117,7 @@ ## displev = optimget (options, "Display", "notify"); funvalchk = strcmpi (optimget (options, "FunValCheck", "off"), "on"); outfcn = optimget (options, "OutputFcn"); - tolx = optimget (options, "TolX", 1e-8); + tolx = optimget (options, "TolX", eps); maxiter = optimget (options, "MaxIter", Inf); maxfev = optimget (options, "MaxFunEvals", Inf); @@ -302,7 +302,7 @@ endif ## If there's an output function, use it now. - if (outfcn) + if (! isempty (outfcn)) optv.funccount = nfev; optv.fval = fval; optv.iteration = niter; diff -r e42d4f152766 -r 8f256148d82b scripts/plot/appearance/datetick.m diff -r e42d4f152766 -r 8f256148d82b scripts/plot/draw/private/__scatter__.m --- a/scripts/plot/draw/private/__scatter__.m Tue Jan 07 16:07:21 2014 -0500 +++ b/scripts/plot/draw/private/__scatter__.m Tue Jan 07 16:07:54 2014 -0500 @@ -84,6 +84,21 @@ c = []; endif + ## Validate inputs + if (nd == 2 && ! size_equal (x, y)) + error ([fcn ": X and Y must have the same size"]); + elseif (nd == 3 && ! size_equal (x, y, z)) + error ([fcn ": X, Y, and Z must have the same size"]); + endif + + if (! isscalar (s) && ! size_equal (x, s)) + error ([fcn ": size of S must match X, Y, and Z"]); + endif + + if (rows (c) > 1 && rows (c) != rows (x)) + error ([fcn ": number of colors in C must match number of points in X"]); + endif + newargs = {}; filled = false; have_marker = false; diff -r e42d4f152766 -r 8f256148d82b scripts/sparse/spdiags.m --- a/scripts/sparse/spdiags.m Tue Jan 07 16:07:21 2014 -0500 +++ b/scripts/sparse/spdiags.m Tue Jan 07 16:07:54 2014 -0500 @@ -17,24 +17,25 @@ ## . ## -*- texinfo -*- -## @deftypefn {Function File} {[@var{b}, @var{c}] =} spdiags (@var{A}) -## @deftypefnx {Function File} {@var{b} =} spdiags (@var{A}, @var{c}) -## @deftypefnx {Function File} {@var{b} =} spdiags (@var{v}, @var{c}, @var{A}) -## @deftypefnx {Function File} {@var{b} =} spdiags (@var{v}, @var{c}, @var{m}, @var{n}) +## @deftypefn {Function File} {@var{B} =} spdiags (@var{A}) +## @deftypefnx {Function File} {[@var{B}, @var{d}] =} spdiags (@var{A}) +## @deftypefnx {Function File} {@var{B} =} spdiags (@var{A}, @var{d}) +## @deftypefnx {Function File} {@var{A} =} spdiags (@var{v}, @var{d}, @var{A}) +## @deftypefnx {Function File} {@var{A} =} spdiags (@var{v}, @var{d}, @var{m}, @var{n}) ## A generalization of the function @code{diag}. Called with a single -## input argument, the non-zero diagonals @var{c} of @var{A} are extracted. +## input argument, the non-zero diagonals @var{d} of @var{A} are extracted. ## With two arguments the diagonals to extract are given by the vector -## @var{c}. +## @var{d}. ## ## The other two forms of @code{spdiags} modify the input matrix by ## replacing the diagonals. They use the columns of @var{v} to replace -## the columns represented by the vector @var{c}. If the sparse matrix +## the diagonals represented by the vector @var{d}. If the sparse matrix ## @var{A} is defined then the diagonals of this matrix are replaced. ## Otherwise a matrix of @var{m} by @var{n} is created with the -## diagonals given by @var{v}. +## diagonals given by the columns of @var{v}. ## -## Negative values of @var{c} represent diagonals below the main -## diagonal, and positive values of @var{c} diagonals above the main +## Negative values of @var{d} represent diagonals below the main +## diagonal, and positive values of @var{d} diagonals above the main ## diagonal. ## ## For example: @@ -52,43 +53,86 @@ ## ## @end deftypefn -function [A, c] = spdiags (v, c, m, n) +function [B, d] = spdiags (v, d, m, n) + + if (nargin < 1 || nargin > 4) + print_usage (); + endif if (nargin == 1 || nargin == 2) - ## extract nonzero diagonals of v into A,c + ## extract nonzero diagonals of A into B,d [nr, nc] = size (v); - [i, j, v] = find (v); + [i, j] = find (v); if (nargin == 1) - ## c contains the active diagonals - c = unique (j-i); + ## d contains the active diagonals + d = unique (j-i); endif - ## FIXME: we can do this without a loop if we are clever - offset = max (min (c, nc-nr), 0); - A = zeros (min (nr, nc), length (c)); - for k = 1:length (c) - idx = find (j-i == c(k)); - A(j(idx)-offset(k),k) = v(idx); + + ## FIXME: Maybe this could be done faster using [i,j,v] = find (v) + ## and then massaging the indices i, j. However, some + ## benchmarking has shown that diag() written in C++ makes + ## the following code faster even with the for loop. + Brows = min (nr, nc); + B = zeros (Brows, length (d)); + for k = 1:length (d) + dn = d(k); + if (dn <= -nr || dn > nc) + continue; + endif + dv = diag (v, dn); + len = rows (dv); + if (dn < 0) + offset = Brows - len + 1; + B(offset:Brows, k) = dv; + else + B(1:len, k) = dv; + endif endfor + elseif (nargin == 3) - ## Replace specific diagonals c of m with v,c + ## Replace specific diagonals d of m with v,d [nr, nc] = size (m); - B = spdiags (m, c); - A = m - spdiags (B, c, nr, nc) + spdiags (v, c, nr, nc); + A = spdiags (m, d); + B = m - spdiags (A, d, nr, nc) + spdiags (v, d, nr, nc); + else - ## Create new matrix of size mxn using v,c + ## Create new matrix of size mxn using v,d [j, i, v] = find (v); - offset = max (min (c(:), n-m), 0); + offset = max (min (d(:), n-m), 0); j = j(:) + offset(i(:)); - i = j - c(:)(i(:)); + i = j - d(:)(i(:)); idx = i > 0 & i <= m & j > 0 & j <= n; - A = sparse (i(idx), j(idx), v(idx), m, n); + B = sparse (i(idx), j(idx), v(idx), m, n); + endif endfunction +%!test +%! [B,d] = spdiags (magic (3)); +%! assert (d, [-2 -1 0 1 2]'); +%! assert (B, [0 0 8 1 6 +%! 0 3 5 7 0 +%! 4 9 2 0 0]); + +%! B = spdiags (magic (3), [-2 1]); +%! assert (B, [0 1; 0 7; 4 0]); + +%!test +%! ## Test zero filling for supra- and super-diagonals +%! A(1,3) = 13; +%! A(3,1) = 31; +%! [B, d] = spdiags (A); +%! assert (d, [-2 2]'); +%! assert (B, [0 13; 0 0; 31 0]); + %!assert (spdiags (zeros (1,0),1,1,1), sparse (0)) %!assert (spdiags (zeros (0,1),1,1,1), sparse (0)) -%!assert (spdiags ([0.5 -1 0.5], 0:2, 1, 1), sparse(0.5)) +%!assert (spdiags ([0.5 -1 0.5], 0:2, 1, 1), sparse (0.5)) +%% Test input validation +%!error spdiags () +%!error spdiags (1,2,3,4,5) + diff -r e42d4f152766 -r 8f256148d82b scripts/statistics/base/prctile.m --- a/scripts/statistics/base/prctile.m Tue Jan 07 16:07:21 2014 -0500 +++ b/scripts/statistics/base/prctile.m Tue Jan 07 16:07:54 2014 -0500 @@ -30,10 +30,8 @@ ## ## If @var{p} is unspecified, return the quantiles for @code{[0 25 50 75 100]}. ## The optional argument @var{dim} determines the dimension along which -## the percentiles are calculated. If @var{dim} is omitted, and @var{x} is -## a vector or matrix, it defaults to 1 (column-wise quantiles). When -## @var{x} is an N-D array, @var{dim} defaults to the first non-singleton -## dimension. +## the percentiles are calculated. If @var{dim} is omitted it defaults to the +## the first non-singleton dimension. ## @seealso{quantile} ## @end deftypefn @@ -59,14 +57,10 @@ endif nd = ndims (x); + sz = size (x); if (nargin < 3) - if (nd == 2) - ## If a matrix or vector, always use 1st dimension. - dim = 1; - else - ## If an N-d array, find the first non-singleton dimension. - (dim = find (sz > 1, 1)) || (dim = 1); - endif + ## Find the first non-singleton dimension. + (dim = find (sz > 1, 1)) || (dim = 1); else if (!(isscalar (dim) && dim == fix (dim)) || !(1 <= dim && dim <= nd)) @@ -84,11 +78,26 @@ %!test %! pct = 50; +%! q = prctile (1:4, pct); +%! qa = 2.5; +%! assert (q, qa); %! q = prctile (1:4, pct, 1); %! qa = [1, 2, 3, 4]; %! assert (q, qa); %! q = prctile (1:4, pct, 2); -%! qa = 2.5000; +%! qa = 2.5; +%! assert (q, qa); + +%!test +%! pct = [50 75]; +%! q = prctile (1:4, pct); +%! qa = [2.5 3.5]; +%! assert (q, qa); +%! q = prctile (1:4, pct, 1); +%! qa = [1, 2, 3, 4; 1, 2, 3, 4]; +%! assert (q, qa); +%! q = prctile (1:4, pct, 2); +%! qa = [2.5 3.5]; %! assert (q, qa); %!test diff -r e42d4f152766 -r 8f256148d82b scripts/statistics/base/quantile.m --- a/scripts/statistics/base/quantile.m Tue Jan 07 16:07:21 2014 -0500 +++ b/scripts/statistics/base/quantile.m Tue Jan 07 16:07:54 2014 -0500 @@ -32,10 +32,8 @@ ## If @var{p} is unspecified, return the quantiles for ## @code{[0.00 0.25 0.50 0.75 1.00]}. ## The optional argument @var{dim} determines the dimension along which -## the quantiles are calculated. If @var{dim} is omitted, and @var{x} is -## a vector or matrix, it defaults to 1 (column-wise quantiles). If -## @var{x} is an N-D array, @var{dim} defaults to the first non-singleton -## dimension. +## the quantiles are calculated. If @var{dim} is omitted it defaults to +## the first non-singleton dimension. ## ## The methods available to calculate sample quantiles are the nine methods ## used by R (@url{http://www.r-project.org/}). The default value is @@ -108,7 +106,7 @@ ## Author: Ben Abbott ## Description: Matlab style quantile function of a discrete/continuous distribution -function q = quantile (x, p = [], dim = 1, method = 5) +function q = quantile (x, p = [], dim, method = 5) if (nargin < 1 || nargin > 4) print_usage (); @@ -126,9 +124,14 @@ error ("quantile: P must be a numeric vector"); endif - if (!(isscalar (dim) && dim == fix (dim)) - || !(1 <= dim && dim <= ndims (x))) - error ("quantile: DIM must be an integer and a valid dimension"); + if (nargin < 3) + ## Find the first non-singleton dimension. + (dim = find (size (x) > 1, 1)) || (dim = 1); + else + if (!(isscalar (dim) && dim == fix (dim)) + || !(1 <= dim && dim <= ndims (x))) + error ("quantile: DIM must be an integer and a valid dimension"); + endif endif ## Set the permutation vector. @@ -158,6 +161,30 @@ %!test +%! p = 0.50; +%! q = quantile (1:4, p); +%! qa = 2.5; +%! assert (q, qa); +%! q = quantile (1:4, p, 1); +%! qa = [1, 2, 3, 4]; +%! assert (q, qa); +%! q = quantile (1:4, p, 2); +%! qa = 2.5; +%! assert (q, qa); + +%!test +%! p = [0.50 0.75]; +%! q = quantile (1:4, p); +%! qa = [2.5 3.5]; +%! assert (q, qa); +%! q = quantile (1:4, p, 1); +%! qa = [1, 2, 3, 4; 1, 2, 3, 4]; +%! assert (q, qa); +%! q = quantile (1:4, p, 2); +%! qa = [2.5 3.5]; +%! assert (q, qa); + +%!test %! p = 0.5; %! x = sort (rand (11)); %! q = quantile (x, p); diff -r e42d4f152766 -r 8f256148d82b scripts/statistics/distributions/empirical_pdf.m --- a/scripts/statistics/distributions/empirical_pdf.m Tue Jan 07 16:07:21 2014 -0500 +++ b/scripts/statistics/distributions/empirical_pdf.m Tue Jan 07 16:07:54 2014 -0500 @@ -37,7 +37,16 @@ error ("empirical_pdf: DATA must be a vector"); endif - pdf = discrete_pdf (x, data, ones (size (data))); + uniq_vals = unique (data); + if (numel (data) != numel (uniq_vals)) + ## Handle ties, multiple elements with same value + p = histc (data, uniq_vals); + data = uniq_vals; + else + p = ones (size (data)); + endif + + pdf = discrete_pdf (x, data, p); endfunction @@ -52,6 +61,9 @@ %!assert (empirical_pdf (single (x), v), single (y)) %!assert (empirical_pdf (x, single (v)), single (y)) +%% Test distribution with ties +%!assert (empirical_pdf (2, [1 2 3 2]), 0.5) + %% Test input validation %!error empirical_pdf () %!error empirical_pdf (1) diff -r e42d4f152766 -r 8f256148d82b scripts/testfun/__run_test_suite__.m --- a/scripts/testfun/__run_test_suite__.m Tue Jan 07 16:07:21 2014 -0500 +++ b/scripts/testfun/__run_test_suite__.m Tue Jan 07 16:07:54 2014 -0500 @@ -66,7 +66,7 @@ dsk += sk; endfor puts ("\nSummary:\n\n"); - nfail = dn - dp; + nfail = dn - dp - dxf; printf (" PASS %6d\n", dp); printf (" FAIL %6d\n", nfail); if (dxf > 0) @@ -116,16 +116,22 @@ endfunction function print_test_file_name (nm) - filler = repmat (".", 1, 55-length (nm)); + filler = repmat (".", 1, 60-length (nm)); printf (" %s %s", nm, filler); endfunction -function print_pass_fail (n, p) - if (n > 0) - printf (" PASS %4d/%-4d", p, n); - nfail = n - p; +function print_pass_fail (p, n, xf, sk) + if ((n + sk) > 0) + printf (" PASS %4d/%-4d", p, n); + nfail = n - p - xf; if (nfail > 0) - printf (" FAIL %d", nfail); + printf ("\n%71s %3d", "FAIL ", nfail); + endif + if (sk > 0) + printf ("\n%71s %3d", "SKIP ", sk); + endif + if (xf > 0) + printf ("\n%71s %3d", "XFAIL", xf); endif endif puts ("\n"); @@ -190,7 +196,7 @@ if (has_tests (ffnm)) print_test_file_name (nm); [p, n, xf, sk] = test (nm, "quiet", fid); - print_pass_fail (n, p); + print_pass_fail (p, n, xf, sk); files_with_tests(end+1) = ffnm; else files_with_no_tests(end+1) = ffnm; @@ -241,7 +247,7 @@ tmp = strrep (tmp, [topbuilddir, filesep], ""); print_test_file_name (tmp); [p, n, xf, sk] = test (f, "quiet", fid); - print_pass_fail (n, p); + print_pass_fail (p, n, xf, sk); dp += p; dn += n; dxf += xf; diff -r e42d4f152766 -r 8f256148d82b scripts/testfun/rundemos.m --- a/scripts/testfun/rundemos.m Tue Jan 07 16:07:21 2014 -0500 +++ b/scripts/testfun/rundemos.m Tue Jan 07 16:07:54 2014 -0500 @@ -42,7 +42,7 @@ if (directory(end) == '/' || directory(end) == '\') directory(end) = []; endif - fullname = find_dir_in_path (directory); + fullname = dir_in_loadpath (directory); if (isempty (fullname)) error ("rundemos: DIRECTORY argument must be a valid pathname"); endif diff -r e42d4f152766 -r 8f256148d82b scripts/testfun/runtests.m --- a/scripts/testfun/runtests.m Tue Jan 07 16:07:21 2014 -0500 +++ b/scripts/testfun/runtests.m Tue Jan 07 16:07:54 2014 -0500 @@ -42,7 +42,7 @@ if (directory(end) == '/' || directory(end) == '\') directory(end) = []; endif - fullname = find_dir_in_path (directory); + fullname = dir_in_loadpath (directory); if (isempty (fullname)) error ("runtests: DIRECTORY argument must be a valid pathname"); endif diff -r e42d4f152766 -r 8f256148d82b scripts/testfun/test.m --- a/scripts/testfun/test.m Tue Jan 07 16:07:21 2014 -0500 +++ b/scripts/testfun/test.m Tue Jan 07 16:07:54 2014 -0500 @@ -265,6 +265,7 @@ ## Assume the block will succeed. __success = 1; __msg = []; + __isxtest = 0; ### DEMO @@ -492,10 +493,17 @@ ### TEST - elseif (strcmp (__type, "test") || strcmp (__type, "xtest")) + elseif (strcmp (__type, "test")) __istest = 1; ## Code will be evaluated below. +### XTEST + + elseif (strcmp (__type, "xtest")) + __istest = 0; + __isxtest = 1; + ## Code will be evaluated below. + ### Comment block. elseif (strcmp (__block(1:1), "#")) @@ -529,6 +537,7 @@ if (strcmp (__type, "xtest")) __msg = sprintf ("%sknown failure\n%s", __signal_fail, lasterr ()); __xfail++; + __success = 0; else __msg = sprintf ("%stest failed\n%s", __signal_fail, lasterr ()); __success = 0; @@ -558,7 +567,7 @@ fflush (__fid); endif endif - if (__success == 0) + if (__success == 0 && !__isxtest) __all_success = 0; ## Stop after one error if not in batch mode. if (! __batch) @@ -571,8 +580,8 @@ return; endif endif - __tests += __istest; - __successes += __success * __istest; + __tests += (__istest || __isxtest); + __successes += __success * (__istest || __isxtest); endfor ## Clear any test functions created eval (__clear, ""); diff -r e42d4f152766 -r 8f256148d82b src/Makefile.am diff -r e42d4f152766 -r 8f256148d82b test/Makefile.am --- a/test/Makefile.am Tue Jan 07 16:07:21 2014 -0500 +++ b/test/Makefile.am Tue Jan 07 16:07:54 2014 -0500 @@ -56,6 +56,7 @@ include bug-36025/module.mk include bug-38236/module.mk include bug-38691/module.mk +include classdef/module.mk include classes/module.mk include class-concat/module.mk include ctor-vs-method/module.mk diff -r e42d4f152766 -r 8f256148d82b test/build-sparse-tests.sh --- a/test/build-sparse-tests.sh Tue Jan 07 16:07:21 2014 -0500 +++ b/test/build-sparse-tests.sh Tue Jan 07 16:07:54 2014 -0500 @@ -513,14 +513,13 @@ # Specific tests for certain mapper functions cat >>$TESTS <. + +%% Test script for classdef OOP. +%% Requires the path to contain the test classes. +%% +%% Note: This script and all classes are also intended to run +%% in MATLAB to test compatibility. Don't break that! +%% +%% To Do: This script tests to ensure that things done correctly work +%% corrrectly. It should also check that things done incorrectly +%% error properly. +%% +%% The classes used for the tests reside in the test/classdef with others +%% in the test directory. +%% +%% The classes provide the ability to test most of the major features +%% of the classdef OOP facilities. There are a number of classes, mostly +%% kind of the same, that create a hierarchy. + +%% Basic classdef tests for value class +%!shared p, q, i, amt +%! q = foo_value_class (); +%! p = foo_value_class (4, 4*12, 50e3); +%! i = p.rate / (12 * 100); +%! amt = (p.principle * i) / (1 - (1 + i)^(-p.term)); +%!assert (isempty (q.rate)); +%!assert (isempty (q.principle)); +%!assert (isempty (q.term)); +%!assert (class (p), "foo_value_class"); +%!assert (p.term, 48); +%!assert (p.rate, 4.0); +%!assert (p.principle, 50e3); +%!assert (p.amount, amt, eps ()) +%!assert (amount (p), amt, eps ()) +%!xtest +%! assert (properties (p), {'rate'; 'term'; 'principle'}) +%!xtest +%! assert (methods (p), {'amount'; 'foo_value_class'}) +%!assert (isempty (foo_value_class().rate)) +%!error foo_value_class.rate + +%% Static method and Constant Property +%!assert (foo_static_method_constant_property.radians_per_cycle, 2*pi); +%!assert (foo_static_method_constant_property().radians_per_cycle, 2*pi); +%!assert (foo_static_method_constant_property().pie, pi); +%!error foo_static_method_constant_property.frequency +%!error foo_static_method_constant_property.cosine +%!test +%! obj = foo_static_method_constant_property; +%! obj.frequency = 10; +%! assert (obj.cosine (0.1), cos (2 * pi * 10 * 0.1), eps ()) +%! assert (obj.sine (0.1), sin (2 * pi * 10 * 0.1), eps ()) + +%!test +%! obj = foo_method_changes_property_size (3); +%! obj = obj.move_element_to_end (2); +%! assert (obj.element, [1 3 2]) diff -r e42d4f152766 -r 8f256148d82b test/classdef/foo_method_changes_property_size.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/classdef/foo_method_changes_property_size.m Tue Jan 07 16:07:54 2014 -0500 @@ -0,0 +1,14 @@ +classdef foo_method_changes_property_size + properties + element; + end + methods + function obj = foo_method_changes_property_size (n) + obj.element = 1:n; + end + function obj = move_element_to_end (obj, n) + obj.element(end+1) = obj.element(n); + obj.element(n) = []; + end + end +end diff -r e42d4f152766 -r 8f256148d82b test/classdef/foo_static_method_constant_property.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/classdef/foo_static_method_constant_property.m Tue Jan 07 16:07:54 2014 -0500 @@ -0,0 +1,30 @@ +classdef foo_static_method_constant_property + properties + frequency; + end + properties (Constant = true) + pie = pi; + end + methods + function obj = foo_static_method_constant_property (f) + if (nargin == 1) + obj.frequency = f; + elseif (nargin ~= 0) + error ('foo_static_method_constant_property:SyntaxError', ... + 'foo_static_method_constant_property: Invalid syntax') + end + end + function res = cosine (obj, t) + res = cos (obj.radians_per_cycle () * obj.frequency * t); + end + function res = sine (obj, t) + res = sin (obj.radians_per_cycle () * obj.frequency * t); + end + end + methods (Static) + function res = radians_per_cycle () + res = 2 * foo_static_method_constant_property.pie; + end + end +end + diff -r e42d4f152766 -r 8f256148d82b test/classdef/foo_value_class.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/classdef/foo_value_class.m Tue Jan 07 16:07:54 2014 -0500 @@ -0,0 +1,28 @@ +classdef foo_value_class + properties + rate; + term; + principle; + end + methods + function obj = foo_value_class (r, t, p) + if (nargin == 3) + obj.rate = r; + obj.term = t; + obj.principle = p; + elseif (nargin ~= 0) + error ('foo_value_class:SyntaxError', ... + 'foo_value_class: Invalid syntax') + end + end + function amt = amount (obj) + i = obj.rate / (12 * 100); + if (i == 0 && obj.term == 0) + amt = obj.principle; + else + amt = (obj.principle * i) / (1 - (1 + i)^(-obj.term)); + end + end + end +end + diff -r e42d4f152766 -r 8f256148d82b test/classdef/module.mk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/classdef/module.mk Tue Jan 07 16:07:54 2014 -0500 @@ -0,0 +1,7 @@ +classdef_FCN_FILES = \ + classdef/foo_method_changes_property_size.m \ + classdef/foo_static_method_constant_property.m \ + classdef/foo_value_class.m \ + classdef/classdef.tst + +FCN_FILES += $(classdef_FCN_FILES) diff -r e42d4f152766 -r 8f256148d82b test/classes/classes.tst diff -r e42d4f152766 -r 8f256148d82b test/classes/module.mk diff -r e42d4f152766 -r 8f256148d82b test/null-assign.tst --- a/test/null-assign.tst Tue Jan 07 16:07:21 2014 -0500 +++ b/test/null-assign.tst Tue Jan 07 16:07:54 2014 -0500 @@ -61,3 +61,49 @@ %!test %! a = ones (3); b = []; fail ("subsasgn (a, substruct ('()', {':',1:2}), b)", ".") +%!test +%! classes = {@int8, @int16, @int32, @int64, ... +%! @uint8, @uint16, @uint32, @uint64, ... +%! @single, @double, @logical}; +%! for i = 1:numel (classes) +%! cls = classes{i}; +%! x = cls ([1, 2, 3]); +%! cls_nm = class (x); +%! x(2) = []; +%! assert (x, cls ([1, 3])); +%! assert (class (x), cls_nm); +%! x(2) = []; +%! assert (x, cls (1)); +%! assert (class (x), cls_nm); +%! x(1) = []; +%! assert (x, cls (zeros (1, 0))); +%! assert (class (x), cls_nm); +%! endfor +%! for i = 1:numel (classes) +%! cls = classes{i}; +%! x = cls ([1, 2, 3]); +%! cls_nm = class (x); +%! x(2) = ''; +%! assert (x, cls ([1, 3])); +%! assert (class (x), cls_nm); +%! x(2) = ''; +%! assert (x, cls (1)); +%! assert (class (x), cls_nm); +%! x(1) = ''; +%! assert (x, cls (zeros (1, 0))); +%! assert (class (x), cls_nm); +%! endfor +%! for i = 1:numel (classes) +%! cls = classes{i}; +%! x = cls ([1, 2, 3]); +%! cls_nm = class (x); +%! x(2) = ""; +%! assert (x, cls ([1, 3])); +%! assert (class (x), cls_nm); +%! x(2) = ""; +%! assert (x, cls (1)); +%! assert (class (x), cls_nm); +%! x(1) = ""; +%! assert (x, cls (zeros (1, 0))); +%! assert (class (x), cls_nm); +%! endfor