GNU Octave 7.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
oct-lvalue.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1996-2022 The Octave Project Developers
4//
5// See the file COPYRIGHT.md in the top-level directory of this
6// distribution or <https://octave.org/copyright/>.
7//
8// This file is part of Octave.
9//
10// Octave is free software: you can redistribute it and/or modify it
11// under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// Octave is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with Octave; see the file COPYING. If not, see
22// <https://www.gnu.org/licenses/>.
23//
24////////////////////////////////////////////////////////////////////////
25
26#if defined (HAVE_CONFIG_H)
27# include "config.h"
28#endif
29
30#include "error.h"
31#include "errwarn.h"
32#include "interpreter-private.h"
33#include "interpreter.h"
34#include "ovl.h"
35#include "oct-lvalue.h"
36#include "ov.h"
37
38namespace octave
39{
40 bool octave_lvalue::is_defined (void) const
41 {
42 return ! is_black_hole () && m_frame->is_defined (m_sym);
43 }
44
46 {
47 return ! is_defined ();
48 }
49
51 {
52 m_frame->assign (m_sym, v);
53 }
54
56 const octave_value& rhs)
57 {
58 if (! is_black_hole ())
59 m_frame->assign (op, m_sym, m_type, m_idx, rhs);
60 }
61
63 {
64 // Return 1 if there is no index because without an index there
65 // should be no way to have a cs-list here. Cs-lists may be passed
66 // around internally but they are not supposed to be stored as
67 // single symbols in a stack frame.
68
69 std::size_t num_indices = m_idx.size ();
70
71 if (num_indices == 0)
72 return 1;
73
74 switch (m_type[num_indices-1])
75 {
76 case '(':
77 return 1;
78
79 case '{':
80 {
81 // FIXME: Duplicate code in '.' case below...
82
83 // Evaluate, skipping the last index.
84
85 std::string tmp_type = m_type;
86 std::list<octave_value_list> tmp_idx = m_idx;
87
88 tmp_type.pop_back ();
89 tmp_idx.pop_back ();
90
91 octave_value tmp = eval_for_numel (tmp_type, tmp_idx);
92
93 octave_value_list tidx = m_idx.back ();
94
95 if (tmp.is_undefined ())
96 {
97 if (tidx.has_magic_colon ())
99
100 tmp = Cell ();
101 }
102 else if (tmp.is_zero_by_zero ()
103 && (tmp.is_matrix_type () || tmp.is_string ()))
104 {
105 tmp = Cell ();
106 }
107
108 return tmp.xnumel (tidx);
109 }
110 break;
111
112 case '.':
113 {
114 // Evaluate, skipping either the last index or the last two
115 // indices if we are looking at "(idx).field".
116
117 std::string tmp_type = m_type;
118 std::list<octave_value_list> tmp_idx = m_idx;
119
120 tmp_type.pop_back ();
121 tmp_idx.pop_back ();
122
123 bool paren_dot = num_indices > 1 && m_type[num_indices-2] == '(';
124
125 // Index for paren operator, if any.
127
128 if (paren_dot)
129 {
130 pidx = tmp_idx.back ();
131
132 tmp_type.pop_back ();
133 tmp_idx.pop_back ();
134 }
135
136 octave_value tmp = eval_for_numel (tmp_type, tmp_idx);
137
138 bool autoconv = (tmp.is_zero_by_zero ()
139 && (tmp.is_matrix_type () || tmp.is_string ()
140 || tmp.iscell ()));
141
142 if (paren_dot)
143 {
144 // Use octave_map, not octave_scalar_map so that the
145 // dimensions are 0x0, not 1x1.
146
147 if (tmp.is_undefined ())
148 {
149 if (pidx.has_magic_colon ())
151
152 tmp = octave_map ();
153 }
154 else if (autoconv)
155 tmp = octave_map ();
156
157 return tmp.xnumel (pidx);
158 }
159 else if (tmp.is_undefined () || autoconv)
160 return 1;
161 else
162 return tmp.xnumel (octave_value_list ());
163 }
164 break;
165
166 default:
168 }
169 }
170
171 void octave_lvalue::set_index (const std::string& t,
172 const std::list<octave_value_list>& i)
173 {
174 if (! m_idx.empty ())
175 error ("invalid index expression in assignment");
176
177 m_type = t;
178 m_idx = i;
179 }
180
182 {
183 bool retval = false;
184
185 if (m_idx.size () == 1)
186 {
187 octave_value_list tmp = m_idx.front ();
188
189 retval = (tmp.length () == 1 && tmp(0).isempty ());
190 }
191
192 return retval;
193 }
194
196 {
197 bool retval = false;
198
199 if (m_idx.size () == 1)
200 {
201 octave_value_list tmp = m_idx.front ();
202
203 retval = (tmp.length () == 1 && tmp(0).is_magic_colon ());
204 }
205
206 return retval;
207 }
208
210 {
211 if (! is_black_hole ())
212 m_frame->non_const_unary_op (op, m_sym, m_type, m_idx);
213 }
214
216 {
217 return (is_black_hole ()
218 ? octave_value () : m_frame->value (m_sym, m_type, m_idx));
219 }
220
222 octave_lvalue::eval_for_numel (const std::string& type,
223 const std::list<octave_value_list>& idx) const
224 {
225 octave_value retval;
226
227 try
228 {
229 retval = m_frame->varval (m_sym);
230
231 if (retval.is_constant () && ! idx.empty ())
232 retval = retval.subsref (type, idx);
233 }
234 catch (const execution_exception&)
235 {
236 // Ignore an error and treat it as undefined. The error
237 // could happen because there is an index is out of range
238 // and we will be resizing a cell array.
239
240 interpreter& interp
241 = __get_interpreter__ ("octave_lvalue::eval_for_numel");
242
243 interp.recover_from_exception ();
244
245 retval = octave_value ();
246 }
247
248 return retval;
249 }
250}
Definition: Cell.h:43
void recover_from_exception(void)
bool index_is_empty(void) const
Definition: oct-lvalue.cc:181
std::list< octave_value_list > m_idx
Definition: oct-lvalue.h:107
void assign(octave_value::assign_op, const octave_value &)
Definition: oct-lvalue.cc:55
void set_index(const std::string &t, const std::list< octave_value_list > &i)
Definition: oct-lvalue.cc:171
bool is_black_hole(void) const
Definition: oct-lvalue.h:55
octave_value value(void) const
Definition: oct-lvalue.cc:215
void define(const octave_value &v)
Definition: oct-lvalue.cc:50
symbol_record m_sym
Definition: oct-lvalue.h:99
octave_idx_type numel(void) const
Definition: oct-lvalue.cc:62
octave_value eval_for_numel(const std::string &type, const std::list< octave_value_list > &idx) const
Definition: oct-lvalue.cc:222
std::shared_ptr< stack_frame > m_frame
Definition: oct-lvalue.h:101
bool is_undefined(void) const
Definition: oct-lvalue.cc:45
std::string m_type
Definition: oct-lvalue.h:105
bool index_is_colon(void) const
Definition: oct-lvalue.cc:195
void unary_op(octave_value::unary_op op)
Definition: oct-lvalue.cc:209
bool is_defined(void) const
Definition: oct-lvalue.cc:40
octave_idx_type length(void) const
Definition: ovl.h:113
bool has_magic_colon(void) const
Definition: ovl.cc:215
bool iscell(void) const
Definition: ov.h:649
octave_value subsref(const std::string &type, const std::list< octave_value_list > &idx)
Definition: ov.h:525
unary_op
Definition: ov.h:77
bool is_constant(void) const
Definition: ov.h:810
bool is_string(void) const
Definition: ov.h:682
octave_idx_type xnumel(const octave_value_list &idx)
Definition: ov.h:516
assign_op
Definition: ov.h:132
bool is_zero_by_zero(void) const
Definition: ov.h:601
bool is_matrix_type(void) const
Definition: ov.h:792
bool is_undefined(void) const
Definition: ov.h:640
void error(const char *fmt,...)
Definition: error.cc:980
#define panic_impossible()
Definition: error.h:411
void err_invalid_inquiry_subscript(void)
Definition: errwarn.cc:77
interpreter & __get_interpreter__(const std::string &who)
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))