1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * expr.c : Expression evaluation in Gnumeric
5 * Copyright (C) 2001-2006 Jody Goldberg (jody@gnome.org)
6 * Copyright (C) 1998-2000 Miguel de Icaza (miguel@gnu.org)
7 * Copyright (C) 2000-2018 Morten Welinder (terra@gnome.org)
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of the
12 * License, or (at your option) version 3.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
24 #include <gnumeric-config.h>
25 #include <glib/gi18n-lib.h>
29 #include "expr-impl.h"
30 #include "expr-name.h"
31 #include "dependent.h"
32 #include "application.h"
37 #include "parse-util.h"
39 #include "number-match.h"
42 #include "parse-util.h"
45 #include <goffice/goffice.h>
51 * Using pools here probably does not save anything, but it's a darn
52 * good debugging tool.
54 #ifndef USE_EXPR_POOLS
55 #define USE_EXPR_POOLS 1
59 /* Memory pools for expressions. */
60 static GOMemChunk
*expression_pool_small
, *expression_pool_big
;
61 #define CHUNK_ALLOC(T,p) ((T*)go_mem_chunk_alloc (p))
62 #define CHUNK_FREE(p,v) go_mem_chunk_free ((p), (v))
64 #define CHUNK_ALLOC(T,c) g_new (T,1)
65 #define CHUNK_FREE(p,v) g_free ((v))
68 /***************************************************************************/
71 * gnm_expr_new_constant:
77 gnm_expr_new_constant (GnmValue
*v
)
81 g_return_val_if_fail (v
!= NULL
, NULL
);
83 ans
= CHUNK_ALLOC (GnmExprConstant
, expression_pool_small
);
86 gnm_expr_constant_init (ans
, v
);
88 return (GnmExpr
*)ans
;
91 /***************************************************************************/
93 static GnmExpr
const *
94 gnm_expr_new_funcallv (GnmFunc
*func
, int argc
, GnmExprConstPtr
*argv
)
97 g_return_val_if_fail (func
, NULL
);
99 ans
= CHUNK_ALLOC (GnmExprFunction
, expression_pool_small
);
101 ans
->oper
= GNM_EXPR_OP_FUNCALL
;
107 return (GnmExpr
*)ans
;
111 gnm_expr_new_funcall (GnmFunc
*func
, GnmExprList
*arg_list
)
113 GnmExprList
*arg_list0
= arg_list
;
114 int argc
= gnm_expr_list_length (arg_list
);
115 GnmExprConstPtr
*argv
= argc
? g_new (GnmExprConstPtr
, argc
) : NULL
;
118 for (i
= 0; arg_list
; i
++, arg_list
= arg_list
->next
)
119 argv
[i
] = arg_list
->data
;
120 gnm_expr_list_free (arg_list0
);
122 return gnm_expr_new_funcallv (func
, argc
, argv
);
126 gnm_expr_new_funcall1 (GnmFunc
*func
,
129 GnmExprConstPtr
*argv
= g_new (GnmExprConstPtr
, 1);
131 return gnm_expr_new_funcallv (func
, 1, argv
);
135 gnm_expr_new_funcall2 (GnmFunc
*func
,
139 GnmExprConstPtr
*argv
= g_new (GnmExprConstPtr
, 2);
142 return gnm_expr_new_funcallv (func
, 2, argv
);
146 gnm_expr_new_funcall3 (GnmFunc
*func
,
151 GnmExprConstPtr
*argv
= g_new (GnmExprConstPtr
, 3);
155 return gnm_expr_new_funcallv (func
, 3, argv
);
159 gnm_expr_new_funcall4 (GnmFunc
*func
,
165 GnmExprConstPtr
*argv
= g_new (GnmExprConstPtr
, 4);
170 return gnm_expr_new_funcallv (func
, 4, argv
);
174 gnm_expr_new_funcall5 (GnmFunc
*func
,
181 GnmExprConstPtr
*argv
= g_new (GnmExprConstPtr
, 5);
187 return gnm_expr_new_funcallv (func
, 5, argv
);
191 /***************************************************************************/
194 gnm_expr_new_unary (GnmExprOp op
, GnmExpr
const *e
)
198 ans
= CHUNK_ALLOC (GnmExprUnary
, expression_pool_small
);
205 return (GnmExpr
*)ans
;
208 /***************************************************************************/
211 gnm_expr_new_binary (GnmExpr
const *l
, GnmExprOp op
, GnmExpr
const *r
)
215 ans
= CHUNK_ALLOC (GnmExprBinary
, expression_pool_small
);
223 return (GnmExpr
*)ans
;
226 /***************************************************************************/
229 gnm_expr_new_name (GnmNamedExpr
*name
,
230 Sheet
*optional_scope
, Workbook
*optional_wb_scope
)
234 ans
= CHUNK_ALLOC (GnmExprName
, expression_pool_big
);
238 ans
->oper
= GNM_EXPR_OP_NAME
;
240 expr_name_ref (name
);
242 ans
->optional_scope
= optional_scope
;
243 ans
->optional_wb_scope
= optional_wb_scope
;
245 return (GnmExpr
*)ans
;
248 /***************************************************************************/
251 gnm_expr_new_cellref (GnmCellRef
const *cr
)
255 ans
= CHUNK_ALLOC (GnmExprCellRef
, expression_pool_big
);
259 ans
->oper
= GNM_EXPR_OP_CELLREF
;
262 return (GnmExpr
*)ans
;
265 /***************************************************************************/
268 gnm_expr_is_array (GnmExpr
const *expr
)
271 (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_ARRAY_ELEM
||
272 GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_ARRAY_CORNER
);
276 * gnm_expr_new_array_corner:
279 * @expr: optionally NULL.
281 * Absorb a referernce to @expr if it is non NULL.
283 static GnmExpr
const *
284 gnm_expr_new_array_corner(int cols
, int rows
, GnmExpr
const *expr
)
286 GnmExprArrayCorner
*ans
;
288 g_return_val_if_fail (!gnm_expr_is_array (expr
), NULL
);
290 ans
= CHUNK_ALLOC (GnmExprArrayCorner
, expression_pool_big
);
294 ans
->oper
= GNM_EXPR_OP_ARRAY_CORNER
;
299 return (GnmExpr
*)ans
;
302 static GnmExpr
const *
303 gnm_expr_new_array_elem (int x
, int y
)
305 GnmExprArrayElem
*ans
;
307 ans
= CHUNK_ALLOC (GnmExprArrayElem
, expression_pool_small
);
311 ans
->oper
= GNM_EXPR_OP_ARRAY_ELEM
;
314 return (GnmExpr
*)ans
;
317 /***************************************************************************/
319 static GnmExpr
const *
320 gnm_expr_new_setv (int argc
, GnmExprConstPtr
*argv
)
322 GnmExprSet
*ans
= CHUNK_ALLOC (GnmExprSet
, expression_pool_small
);
324 ans
->oper
= GNM_EXPR_OP_SET
;
328 return (GnmExpr
*)ans
;
332 gnm_expr_new_set (GnmExprList
*set
)
335 GnmExprConstPtr
*argv
;
336 GnmExprList
*set0
= set
;
338 argc
= gnm_expr_list_length (set
);
339 argv
= argc
? g_new (GnmExprConstPtr
, argc
) : NULL
;
340 for (i
= 0; set
; i
++, set
= set
->next
)
342 gnm_expr_list_free (set0
);
344 return gnm_expr_new_setv (argc
, argv
);
347 /***************************************************************************/
350 * gnm_expr_new_range_ctor:
354 * This function builds a range constructor or something simpler,
355 * but equivalent, if the arguments allow it.
357 * Note: this takes ownership of @l and @r and may delete them.
360 gnm_expr_new_range_ctor (GnmExpr
const *l
, GnmExpr
const *r
)
364 g_return_val_if_fail (l
!= NULL
, NULL
);
365 g_return_val_if_fail (r
!= NULL
, NULL
);
367 if (GNM_EXPR_GET_OPER (l
) != GNM_EXPR_OP_CELLREF
)
369 if (GNM_EXPR_GET_OPER (r
) != GNM_EXPR_OP_CELLREF
)
372 v
= value_new_cellrange_unsafe (&l
->cellref
.ref
, &r
->cellref
.ref
);
375 return gnm_expr_new_constant (v
);
378 return gnm_expr_new_binary (l
, GNM_EXPR_OP_RANGE_CTOR
, r
);
381 /***************************************************************************/
384 gnm_expr_copy (GnmExpr
const *expr
)
386 g_return_val_if_fail (expr
!= NULL
, NULL
);
388 switch (GNM_EXPR_GET_OPER (expr
)) {
389 case GNM_EXPR_OP_RANGE_CTOR
:
390 case GNM_EXPR_OP_INTERSECT
:
391 case GNM_EXPR_OP_ANY_BINARY
:
392 return gnm_expr_new_binary
393 (gnm_expr_copy (expr
->binary
.value_a
),
394 GNM_EXPR_GET_OPER (expr
),
395 gnm_expr_copy (expr
->binary
.value_b
));
397 case GNM_EXPR_OP_ANY_UNARY
:
398 return gnm_expr_new_unary
399 (GNM_EXPR_GET_OPER (expr
),
400 gnm_expr_copy (expr
->unary
.value
));
402 case GNM_EXPR_OP_FUNCALL
: {
403 GnmExprConstPtr
*argv
=
404 g_new (GnmExprConstPtr
, expr
->func
.argc
);
407 for (i
= 0; i
< expr
->func
.argc
; i
++)
408 argv
[i
] = gnm_expr_copy (expr
->func
.argv
[i
]);
410 return gnm_expr_new_funcallv
416 case GNM_EXPR_OP_NAME
:
417 return gnm_expr_new_name
419 expr
->name
.optional_scope
,
420 expr
->name
.optional_wb_scope
);
422 case GNM_EXPR_OP_CONSTANT
:
423 return gnm_expr_new_constant
424 (value_dup (expr
->constant
.value
));
426 case GNM_EXPR_OP_CELLREF
:
427 return gnm_expr_new_cellref (&expr
->cellref
.ref
);
429 case GNM_EXPR_OP_ARRAY_CORNER
:
430 return gnm_expr_new_array_corner
431 (expr
->array_corner
.cols
, expr
->array_corner
.rows
,
432 gnm_expr_copy (expr
->array_corner
.expr
));
434 case GNM_EXPR_OP_ARRAY_ELEM
:
435 return gnm_expr_new_array_elem
439 case GNM_EXPR_OP_SET
: {
440 GnmExprConstPtr
*argv
=
441 g_new (GnmExprConstPtr
, expr
->set
.argc
);
444 for (i
= 0; i
< expr
->set
.argc
; i
++)
445 argv
[i
] = gnm_expr_copy (expr
->set
.argv
[i
]);
447 return gnm_expr_new_setv
452 #ifndef DEBUG_SWITCH_ENUM
454 g_assert_not_reached ();
464 gnm_expr_free (GnmExpr
const *expr
)
466 g_return_if_fail (expr
!= NULL
);
468 switch (GNM_EXPR_GET_OPER (expr
)) {
469 case GNM_EXPR_OP_RANGE_CTOR
:
470 case GNM_EXPR_OP_INTERSECT
:
471 case GNM_EXPR_OP_ANY_BINARY
:
472 gnm_expr_free (expr
->binary
.value_a
);
473 gnm_expr_free (expr
->binary
.value_b
);
474 CHUNK_FREE (expression_pool_small
, (gpointer
)expr
);
477 case GNM_EXPR_OP_FUNCALL
: {
480 for (i
= 0; i
< expr
->func
.argc
; i
++)
481 gnm_expr_free (expr
->func
.argv
[i
]);
482 g_free (expr
->func
.argv
);
483 gnm_func_unref (expr
->func
.func
);
484 CHUNK_FREE (expression_pool_small
, (gpointer
)expr
);
488 case GNM_EXPR_OP_NAME
:
489 expr_name_unref (expr
->name
.name
);
490 CHUNK_FREE (expression_pool_big
, (gpointer
)expr
);
493 case GNM_EXPR_OP_CONSTANT
:
494 value_release ((GnmValue
*)expr
->constant
.value
);
495 CHUNK_FREE (expression_pool_small
, (gpointer
)expr
);
498 case GNM_EXPR_OP_CELLREF
:
499 CHUNK_FREE (expression_pool_big
, (gpointer
)expr
);
502 case GNM_EXPR_OP_ANY_UNARY
:
503 gnm_expr_free (expr
->unary
.value
);
504 CHUNK_FREE (expression_pool_small
, (gpointer
)expr
);
507 case GNM_EXPR_OP_ARRAY_CORNER
:
508 value_release (expr
->array_corner
.value
);
509 // A proper corner will not have NULL here, but we explicitly allow it
510 // during construction, so allow it here too.
511 if (expr
->array_corner
.expr
)
512 gnm_expr_free (expr
->array_corner
.expr
);
513 CHUNK_FREE (expression_pool_big
, (gpointer
)expr
);
516 case GNM_EXPR_OP_ARRAY_ELEM
:
517 CHUNK_FREE (expression_pool_small
, (gpointer
)expr
);
520 case GNM_EXPR_OP_SET
: {
523 for (i
= 0; i
< expr
->set
.argc
; i
++)
524 gnm_expr_free (expr
->set
.argv
[i
]);
525 g_free (expr
->set
.argv
);
526 CHUNK_FREE (expression_pool_small
, (gpointer
)expr
);
530 #ifndef DEBUG_SWITCH_ENUM
532 g_assert_not_reached ();
539 gnm_expr_get_type (void)
544 t
= g_boxed_type_register_static ("GnmExpr",
545 (GBoxedCopyFunc
)gnm_expr_copy
,
546 (GBoxedFreeFunc
)gnm_expr_free
);
552 gnm_expr_array_corner_get_type (void)
557 t
= g_boxed_type_register_static ("GnmExprArrayCorner",
558 (GBoxedCopyFunc
)gnm_expr_copy
,
559 (GBoxedFreeFunc
)gnm_expr_free
);
567 * Return:s TRUE if the supplied expressions are exactly the
568 * same. No eval position is used to see if they are effectively the same.
569 * Named expressions must refer the same name, having equivalent names is
573 gnm_expr_equal (GnmExpr
const *a
, GnmExpr
const *b
)
578 g_return_val_if_fail (a
!= NULL
, FALSE
);
579 g_return_val_if_fail (b
!= NULL
, FALSE
);
581 if (GNM_EXPR_GET_OPER (a
) != GNM_EXPR_GET_OPER (b
))
584 switch (GNM_EXPR_GET_OPER (a
)) {
585 case GNM_EXPR_OP_RANGE_CTOR
:
586 case GNM_EXPR_OP_INTERSECT
:
587 case GNM_EXPR_OP_ANY_BINARY
:
588 return gnm_expr_equal (a
->binary
.value_a
, b
->binary
.value_a
) &&
589 gnm_expr_equal (a
->binary
.value_b
, b
->binary
.value_b
);
591 case GNM_EXPR_OP_ANY_UNARY
:
592 return gnm_expr_equal (a
->unary
.value
, b
->unary
.value
);
594 case GNM_EXPR_OP_FUNCALL
: {
597 if (a
->func
.func
!= b
->func
.func
||
598 a
->func
.argc
!= b
->func
.argc
)
601 for (i
= 0; i
< a
->func
.argc
; i
++)
602 if (!gnm_expr_equal (a
->func
.argv
[i
], b
->func
.argv
[i
]))
607 case GNM_EXPR_OP_NAME
:
608 return a
->name
.name
== b
->name
.name
&&
609 a
->name
.optional_scope
== b
->name
.optional_scope
&&
610 a
->name
.optional_wb_scope
== b
->name
.optional_wb_scope
;
612 case GNM_EXPR_OP_CELLREF
:
613 return gnm_cellref_equal (&a
->cellref
.ref
, &b
->cellref
.ref
);
615 case GNM_EXPR_OP_CONSTANT
:
616 return value_equal (a
->constant
.value
, b
->constant
.value
);
618 case GNM_EXPR_OP_ARRAY_CORNER
: {
619 GnmExprArrayCorner
const *aa
= &a
->array_corner
;
620 GnmExprArrayCorner
const *ab
= &b
->array_corner
;
622 return aa
->cols
== ab
->cols
&&
623 aa
->rows
== ab
->rows
&&
624 gnm_expr_equal (aa
->expr
, ab
->expr
);
626 case GNM_EXPR_OP_ARRAY_ELEM
: {
627 GnmExprArrayElem
const *aa
= &a
->array_elem
;
628 GnmExprArrayElem
const *ab
= &b
->array_elem
;
629 return aa
->x
== ab
->x
&& aa
->y
== ab
->y
;
632 case GNM_EXPR_OP_SET
: {
635 if (a
->set
.argc
!= b
->set
.argc
)
638 for (i
= 0; i
< a
->set
.argc
; i
++)
639 if (!gnm_expr_equal (a
->set
.argv
[i
], b
->set
.argv
[i
]))
649 array_elem_get_corner (GnmExprArrayElem
const *elem
,
650 Sheet
const *sheet
, GnmCellPos
const *pos
)
652 GnmCell
*corner
= sheet_cell_get (sheet
,
653 pos
->col
- elem
->x
, pos
->row
- elem
->y
);
655 /* Sanity check incase the corner gets removed for some reason */
656 g_return_val_if_fail (corner
!= NULL
, NULL
);
657 g_return_val_if_fail (gnm_cell_has_expr (corner
), NULL
);
658 g_return_val_if_fail (corner
->base
.texpr
!= (void *)0xdeadbeef, NULL
);
659 g_return_val_if_fail (GNM_IS_EXPR_TOP (corner
->base
.texpr
), NULL
);
665 gnm_expr_extract_ref (GnmRangeRef
*res
, GnmExpr
const *expr
,
666 GnmEvalPos
const *pos
, GnmExprEvalFlags flags
)
668 switch (GNM_EXPR_GET_OPER (expr
)) {
669 case GNM_EXPR_OP_FUNCALL
: {
670 gboolean failed
= TRUE
;
675 ei
.func_call
= &expr
->func
;
677 v
= function_call_with_exprs (&ei
);
680 if (VALUE_IS_CELLRANGE (v
)) {
681 *res
= v
->v_range
.cell
;
689 case GNM_EXPR_OP_CELLREF
:
690 res
->a
= expr
->cellref
.ref
;
691 res
->b
= expr
->cellref
.ref
;
694 case GNM_EXPR_OP_CONSTANT
: {
695 GnmValue
const *v
= expr
->constant
.value
;
696 if (VALUE_IS_CELLRANGE (v
)) {
697 *res
= v
->v_range
.cell
;
703 case GNM_EXPR_OP_NAME
:
704 if (!expr_name_is_active (expr
->name
.name
))
706 return gnm_expr_extract_ref (res
, expr
->name
.name
->texpr
->expr
,
714 static inline GnmValue
*
715 handle_empty (GnmValue
*res
, GnmExprEvalFlags flags
)
718 return (flags
& GNM_EXPR_EVAL_PERMIT_EMPTY
)
719 ? NULL
: value_new_int (0);
721 if (VALUE_IS_EMPTY (res
)) {
723 return (flags
& GNM_EXPR_EVAL_PERMIT_EMPTY
)
724 ? NULL
: value_new_int (0);
730 * value_intersection:
731 * @v: a VALUE_CELLRANGE or VALUE_ARRAY
734 * Handle the implicit union of a single row or column with the eval position.
736 * NOTE : We do not need to know if this is expression is being evaluated as an
737 * array or not because we can differentiate based on the required type for the
740 * Always release the value passed in.
743 * If the intersection succeeded return a duplicate of the value
744 * at the intersection point. This value needs to be freed.
745 * NULL if there is no intersection
746 * Returns the upper left corner of an array.
749 value_intersection (GnmValue
*v
, GnmEvalPos
const *pos
)
751 GnmValue
*res
= NULL
;
753 Sheet
*start_sheet
, *end_sheet
;
754 gboolean found
= FALSE
;
756 if (VALUE_IS_ARRAY (v
)) {
757 res
= (v
->v_array
.x
== 0 || v
->v_array
.y
== 0)
758 ? value_new_error_VALUE (NULL
)
759 : value_dup (v
->v_array
.vals
[0][0]);
764 /* inverted ranges */
765 gnm_rangeref_normalize (&v
->v_range
.cell
, pos
, &start_sheet
, &end_sheet
, &r
);
768 if (start_sheet
== end_sheet
|| end_sheet
== NULL
) {
769 int col
= pos
->eval
.col
;
770 int row
= pos
->eval
.row
;
772 if (pos
->dep
&& !dependent_is_cell (pos
->dep
)) {
773 /* See bug #142412. */
777 } else if (r
.start
.row
== r
.end
.row
) {
778 if (r
.start
.col
<= col
&& col
<= r
.end
.col
) {
781 } else if (r
.start
.col
== r
.end
.col
) {
786 } else if (r
.start
.col
== r
.end
.col
) {
787 if (r
.start
.row
<= row
&& row
<= r
.end
.row
) {
793 GnmCell
*cell
= sheet_cell_get (
794 eval_sheet (start_sheet
, pos
->sheet
),
797 return value_new_empty ();
798 gnm_cell_eval (cell
);
799 return value_dup (cell
->value
);
803 return value_new_error_VALUE (pos
);
807 bin_arith (GnmExpr
const *expr
, GnmEvalPos
const *ep
,
808 GnmValue
const *a
, GnmValue
const *b
)
810 gnm_float
const va
= value_get_as_float (a
);
811 gnm_float
const vb
= value_get_as_float (b
);
814 switch (GNM_EXPR_GET_OPER (expr
)) {
815 case GNM_EXPR_OP_ADD
:
819 case GNM_EXPR_OP_SUB
:
823 case GNM_EXPR_OP_MULT
:
827 case GNM_EXPR_OP_DIV
:
829 return value_new_error_DIV0 (ep
);
833 case GNM_EXPR_OP_EXP
:
834 if ((va
== 0 && vb
<= 0) || (va
< 0 && vb
!= (int)vb
))
835 return value_new_error_NUM (ep
);
837 res
= gnm_pow (va
, vb
);
841 g_assert_not_reached ();
844 if (gnm_finite (res
))
845 return value_new_float (res
);
847 return value_new_error_NUM (ep
);
851 bin_cmp (GnmExprOp op
, GnmValDiff comp
, GnmEvalPos
const *ep
)
853 if (comp
== TYPE_MISMATCH
) {
854 /* TODO TODO TODO : Make error more informative
855 * regarding what is comparing to what
857 /* For equality comparisons even errors are ok */
858 if (op
== GNM_EXPR_OP_EQUAL
)
859 return value_new_bool (FALSE
);
860 if (op
== GNM_EXPR_OP_NOT_EQUAL
)
861 return value_new_bool (TRUE
);
863 return value_new_error_VALUE (ep
);
867 case GNM_EXPR_OP_EQUAL
: return value_new_bool (comp
== IS_EQUAL
);
868 case GNM_EXPR_OP_GT
: return value_new_bool (comp
== IS_GREATER
);
869 case GNM_EXPR_OP_LT
: return value_new_bool (comp
== IS_LESS
);
870 case GNM_EXPR_OP_NOT_EQUAL
: return value_new_bool (comp
!= IS_EQUAL
);
871 case GNM_EXPR_OP_LTE
: return value_new_bool (comp
!= IS_GREATER
);
872 case GNM_EXPR_OP_GTE
: return value_new_bool (comp
!= IS_LESS
);
874 #ifndef DEBUG_SWITCH_ENUM
876 g_assert_not_reached ();
879 return value_new_error (ep
, _("Internal type error"));
883 cb_bin_cmp (GnmEvalPos
const *ep
, GnmValue
const *a
, GnmValue
const *b
,
886 if (a
!= NULL
&& VALUE_IS_ERROR (a
))
887 return value_dup (a
);
888 if (b
!= NULL
&& VALUE_IS_ERROR (b
))
889 return value_dup (b
);
890 return bin_cmp (GNM_EXPR_GET_OPER (expr
), value_compare (a
, b
, FALSE
), ep
);
894 cb_bin_arith (GnmEvalPos
const *ep
, GnmValue
const *a
, GnmValue
const *b
,
897 GnmValue
*res
, *va
, *vb
;
899 if (a
!= NULL
&& VALUE_IS_ERROR (a
))
900 return value_dup (a
);
901 if (b
!= NULL
&& VALUE_IS_ERROR (b
))
902 return value_dup (b
);
903 if (VALUE_IS_EMPTY (a
))
904 a
= va
= (GnmValue
*)value_zero
;
905 else if (VALUE_IS_STRING (a
)) {
906 va
= format_match_number (value_peek_string (a
), NULL
,
907 sheet_date_conv (ep
->sheet
));
909 return value_new_error_VALUE (ep
);
910 } else if (!VALUE_IS_NUMBER (a
))
911 return value_new_error_VALUE (ep
);
914 if (VALUE_IS_EMPTY (b
))
915 b
= vb
= (GnmValue
*)value_zero
;
916 else if (VALUE_IS_STRING (b
)) {
917 vb
= format_match_number (value_peek_string (b
), NULL
,
918 sheet_date_conv (ep
->sheet
));
922 return value_new_error_VALUE (ep
);
924 } else if (!VALUE_IS_NUMBER (b
)) {
927 return value_new_error_VALUE (ep
);
931 res
= bin_arith (expr
, ep
, va
, vb
);
940 cb_bin_cat (GnmEvalPos
const *ep
, GnmValue
const *a
, GnmValue
const *b
,
943 if (a
!= NULL
&& VALUE_IS_ERROR (a
))
944 return value_dup (a
);
945 if (b
!= NULL
&& VALUE_IS_ERROR (b
))
946 return value_dup (b
);
949 return value_new_string (value_peek_string (b
));
951 return value_new_string ("");
952 } else if (b
== NULL
)
953 return value_new_string (value_peek_string (a
));
955 char *tmp
= g_strconcat (value_peek_string (a
),
956 value_peek_string (b
), NULL
);
957 return value_new_string_nocopy (tmp
);
961 typedef GnmValue
*(*BinOpImplicitIteratorFunc
) (GnmEvalPos
const *ep
,
966 GnmEvalPos
const *ep
;
968 GnmValue
const *a
, *b
;
969 BinOpImplicitIteratorFunc func
;
971 /* multiply by 0 in unused dimensions.
972 * this is simpler than lots of conditions
973 * state->use_x.a ? x : 0
979 } BinOpImplicitIteratorState
;
982 cb_implicit_iter_a_and_b (GnmValueIter
const *v_iter
,
983 BinOpImplicitIteratorState
const *state
)
985 state
->res
->v_array
.vals
[v_iter
->x
][v_iter
->y
] =
986 (*state
->func
) (v_iter
->ep
,
987 value_area_get_x_y (state
->a
,
988 state
->x
.a
* v_iter
->x
,
989 state
->y
.a
* v_iter
->y
, v_iter
->ep
),
990 value_area_get_x_y (state
->b
,
991 state
->x
.b
* v_iter
->x
,
992 state
->y
.b
* v_iter
->y
, v_iter
->ep
),
997 cb_implicit_iter_a_to_scalar_b (GnmValueIter
const *v_iter
,
998 BinOpImplicitIteratorState
const *state
)
1000 state
->res
->v_array
.vals
[v_iter
->x
][v_iter
->y
] =
1001 (*state
->func
) (v_iter
->ep
,
1002 v_iter
->v
, state
->b
, state
->user_data
);
1006 /* This is only triggered if something returns an array or a range which can
1007 * only happen if we are in array eval mode. */
1009 bin_array_iter_a (GnmEvalPos
const *ep
,
1010 GnmValue
*a
, GnmValue
*b
,
1011 BinOpImplicitIteratorFunc func
,
1012 GnmExpr
const *expr
)
1014 BinOpImplicitIteratorState iter_info
;
1016 /* a must be a cellrange or array, it can not be NULL */
1018 iter_info
.func
= func
;
1019 iter_info
.user_data
= (gpointer
) expr
;
1024 * Use matching positions unless the dimension is singular, in which
1025 * case use the zero item
1026 * res[x][y] = f(a[singular.a.x ? 0 : x, b[singular.b.x ? 0 : x)
1028 * If both items have non-singular sizes for
1029 * the same dimension use the min size (see samples/array.xls) */
1031 (VALUE_IS_CELLRANGE (b
) || VALUE_IS_ARRAY (b
))) {
1032 int sa
, sb
, w
= 1, h
= 1;
1034 sa
= value_area_get_width (a
, ep
);
1035 sb
= value_area_get_width (b
, ep
);
1036 if ((iter_info
.x
.a
= (sa
== 1) ? 0 : 1))
1038 if ((iter_info
.x
.b
= (sb
== 1) ? 0 : 1) && (w
> sb
|| w
== 1))
1041 sa
= value_area_get_height (a
, ep
);
1042 sb
= value_area_get_height (b
, ep
);
1043 if ((iter_info
.y
.a
= (sa
== 1) ? 0 : 1))
1045 if ((iter_info
.y
.b
= (sb
== 1) ? 0 : 1) && (h
> sb
|| h
== 1))
1048 iter_info
.res
= value_new_array_empty (w
, h
);
1049 value_area_foreach (iter_info
.res
, ep
, CELL_ITER_ALL
,
1050 (GnmValueIterFunc
) cb_implicit_iter_a_and_b
, &iter_info
);
1052 iter_info
.res
= value_new_array_empty (
1053 value_area_get_width (a
, ep
),
1054 value_area_get_height (a
, ep
));
1055 value_area_foreach (a
, ep
, CELL_ITER_ALL
,
1056 (GnmValueIterFunc
) cb_implicit_iter_a_to_scalar_b
, &iter_info
);
1061 return iter_info
.res
;
1065 cb_implicit_iter_b_to_scalar_a (GnmValueIter
const *v_iter
,
1066 BinOpImplicitIteratorState
const *state
)
1068 state
->res
->v_array
.vals
[v_iter
->x
][v_iter
->y
] =
1069 (*state
->func
) (v_iter
->ep
,
1070 state
->a
, v_iter
->v
, state
->user_data
);
1074 bin_array_iter_b (GnmEvalPos
const *ep
,
1075 GnmValue
*a
, GnmValue
*b
,
1076 BinOpImplicitIteratorFunc func
,
1077 GnmExpr
const *expr
)
1079 BinOpImplicitIteratorState iter_info
;
1081 iter_info
.func
= func
;
1082 iter_info
.user_data
= (gpointer
) expr
;
1086 /* b must be a cellrange or array, it cannot be NULL */
1087 iter_info
.res
= value_new_array_empty (
1088 value_area_get_width (b
, ep
),
1089 value_area_get_height (b
, ep
));
1090 value_area_foreach (b
, ep
, CELL_ITER_ALL
,
1091 (GnmValueIterFunc
) cb_implicit_iter_b_to_scalar_a
, &iter_info
);
1095 return iter_info
.res
;
1099 negate_value (GnmValue
const *v
)
1101 if (VALUE_IS_NUMBER (v
)) {
1102 GnmValue
*tmp
= value_new_float (0 - value_get_as_float (v
));
1103 value_set_fmt (tmp
, VALUE_FMT (v
));
1110 cb_iter_unary_neg (GnmValueIter
const *v_iter
, GnmValue
*res
)
1112 GnmValue
const *v
= v_iter
->v
;
1113 GnmValue
*tmp
= NULL
;
1115 if (VALUE_IS_EMPTY (v
))
1116 tmp
= value_new_int (0);
1117 else if (VALUE_IS_ERROR (v
))
1118 tmp
= value_dup (v
);
1119 else if (VALUE_IS_STRING (v
)) {
1120 GnmValue
*conv
= format_match_number (
1121 value_peek_string (v
), NULL
,
1122 sheet_date_conv (v_iter
->ep
->sheet
));
1124 tmp
= negate_value (conv
);
1125 value_release (conv
);
1128 /* BOOL goes here. */
1129 tmp
= negate_value (v
);
1133 tmp
= value_new_error_VALUE (v_iter
->ep
);
1134 res
->v_array
.vals
[v_iter
->x
][v_iter
->y
] = tmp
;
1139 cb_iter_percentage (GnmValueIter
const *v_iter
, GnmValue
*res
)
1141 GnmValue
const *v
= v_iter
->v
;
1144 if (VALUE_IS_EMPTY (v
))
1145 tmp
= value_new_int (0);
1146 else if (VALUE_IS_ERROR (v
))
1147 tmp
= value_dup (v
);
1149 GnmValue
*conv
= NULL
;
1150 if (VALUE_IS_STRING (v
)) {
1151 conv
= format_match_number (
1152 value_peek_string (v
), NULL
,
1153 sheet_date_conv (v_iter
->ep
->sheet
));
1158 if (VALUE_IS_NUMBER (v
)){
1159 tmp
= value_new_float (value_get_as_float (v
) / 100);
1160 value_set_fmt (tmp
, go_format_default_percentage ());
1162 tmp
= value_new_error_VALUE (v_iter
->ep
);
1164 value_release (conv
);
1167 res
->v_array
.vals
[v_iter
->x
][v_iter
->y
] = tmp
;
1172 gnm_expr_range_op (GnmExpr
const *expr
, GnmEvalPos
const *ep
,
1173 GnmExprEvalFlags flags
)
1175 GnmRangeRef a_ref
, b_ref
;
1176 GnmRange a_range
, b_range
, res_range
;
1177 Sheet
*a_start
, *a_end
, *b_start
, *b_end
;
1178 GnmValue
*res
= NULL
;
1180 if (gnm_expr_extract_ref (&a_ref
, expr
->binary
.value_a
, ep
, flags
) ||
1181 gnm_expr_extract_ref (&b_ref
, expr
->binary
.value_b
, ep
, flags
))
1182 return value_new_error_REF (ep
);
1184 gnm_rangeref_normalize (&a_ref
, ep
, &a_start
, &a_end
, &a_range
);
1185 gnm_rangeref_normalize (&b_ref
, ep
, &b_start
, &b_end
, &b_range
);
1187 switch (GNM_EXPR_GET_OPER (expr
)) {
1188 case GNM_EXPR_OP_RANGE_CTOR
:
1189 res_range
= range_union (&a_range
, &b_range
);
1190 /* b_range might be on a bigger sheet. */
1191 range_ensure_sanity (&res_range
, a_start
);
1193 case GNM_EXPR_OP_INTERSECT
:
1194 /* 3D references not allowed. */
1195 if (a_start
!= a_end
|| b_start
!= b_end
)
1196 return value_new_error_VALUE (ep
);
1198 /* Must be same sheet. */
1199 if (a_start
!= b_start
)
1200 return value_new_error_VALUE (ep
);
1202 if (!range_intersection (&res_range
, &a_range
, &b_range
))
1203 return value_new_error_NULL (ep
);
1206 g_assert_not_reached ();
1210 res
= value_new_cellrange_r (a_start
, &res_range
);
1211 dependent_add_dynamic_dep (ep
->dep
, &res
->v_range
.cell
);
1212 if (!(flags
& GNM_EXPR_EVAL_PERMIT_NON_SCALAR
)) {
1213 res
= value_intersection (res
, ep
);
1214 return (res
!= NULL
)
1215 ? handle_empty (res
, flags
)
1216 : value_new_error_VALUE (ep
);
1227 * if GNM_EXPR_EVAL_PERMIT_EMPTY is not set then return int(0) if the
1228 * expression returns empty, or the value of an unused cell.
1231 gnm_expr_eval (GnmExpr
const *expr
, GnmEvalPos
const *pos
,
1232 GnmExprEvalFlags flags
)
1234 GnmValue
*res
= NULL
, *a
= NULL
, *b
= NULL
;
1236 g_return_val_if_fail (expr
!= NULL
, handle_empty (NULL
, flags
));
1237 g_return_val_if_fail (pos
!= NULL
, handle_empty (NULL
, flags
));
1240 switch (GNM_EXPR_GET_OPER (expr
)){
1241 case GNM_EXPR_OP_EQUAL
:
1242 case GNM_EXPR_OP_NOT_EQUAL
:
1243 case GNM_EXPR_OP_GT
:
1244 case GNM_EXPR_OP_GTE
:
1245 case GNM_EXPR_OP_LT
:
1246 case GNM_EXPR_OP_LTE
:
1247 flags
|= GNM_EXPR_EVAL_PERMIT_EMPTY
;
1248 flags
&= ~GNM_EXPR_EVAL_WANT_REF
;
1250 a
= gnm_expr_eval (expr
->binary
.value_a
, pos
, flags
);
1252 if (VALUE_IS_ERROR (a
))
1254 if (VALUE_IS_CELLRANGE (a
) || VALUE_IS_ARRAY (a
))
1255 return bin_array_iter_a (pos
, a
,
1256 gnm_expr_eval (expr
->binary
.value_b
, pos
, flags
),
1257 (BinOpImplicitIteratorFunc
) cb_bin_cmp
,
1261 b
= gnm_expr_eval (expr
->binary
.value_b
, pos
, flags
);
1263 if (VALUE_IS_ERROR (b
)) {
1267 if (VALUE_IS_CELLRANGE (b
) || VALUE_IS_ARRAY (b
))
1268 return bin_array_iter_b (pos
, a
, b
,
1269 (BinOpImplicitIteratorFunc
) cb_bin_cmp
,
1273 res
= bin_cmp (GNM_EXPR_GET_OPER (expr
), value_compare (a
, b
, FALSE
), pos
);
1278 case GNM_EXPR_OP_ADD
:
1279 case GNM_EXPR_OP_SUB
:
1280 case GNM_EXPR_OP_MULT
:
1281 case GNM_EXPR_OP_DIV
:
1282 case GNM_EXPR_OP_EXP
:
1286 * 2) #!VALUE error if A is not a number
1288 * 4) #!VALUE error if B is not a number
1289 * 5) result of operation, or error specific to the operation
1292 /* Guarantees value != NULL */
1293 flags
&= ~GNM_EXPR_EVAL_PERMIT_EMPTY
;
1294 flags
&= ~GNM_EXPR_EVAL_WANT_REF
;
1296 /* 1) Error from A */
1297 a
= gnm_expr_eval (expr
->binary
.value_a
, pos
, flags
);
1298 if (VALUE_IS_ERROR (a
))
1299 return value_error_set_pos (&a
->v_err
, pos
);
1301 /* 2) #!VALUE error if A is not a number */
1302 if (VALUE_IS_STRING (a
)) {
1303 GnmValue
*tmp
= format_match_number (value_peek_string (a
), NULL
,
1304 sheet_date_conv (pos
->sheet
));
1308 return value_new_error_VALUE (pos
);
1310 } else if (VALUE_IS_CELLRANGE (a
) || VALUE_IS_ARRAY (a
)) {
1311 b
= gnm_expr_eval (expr
->binary
.value_b
, pos
, flags
);
1312 if (VALUE_IS_STRING (b
)) {
1313 res
= format_match_number (value_peek_string (b
), NULL
,
1314 sheet_date_conv (pos
->sheet
));
1316 b
= (res
== NULL
) ? value_new_error_VALUE (pos
) : res
;
1318 return bin_array_iter_a (pos
, a
, b
,
1319 (BinOpImplicitIteratorFunc
) cb_bin_arith
,
1321 } else if (!VALUE_IS_NUMBER (a
)) {
1323 return value_new_error_VALUE (pos
);
1326 /* 3) Error from B */
1327 b
= gnm_expr_eval (expr
->binary
.value_b
, pos
, flags
);
1328 if (VALUE_IS_ERROR (b
)) {
1330 return value_error_set_pos (&b
->v_err
, pos
);
1333 /* 4) #!VALUE error if B is not a number */
1334 if (VALUE_IS_STRING (b
)) {
1335 GnmValue
*tmp
= format_match_number (value_peek_string (b
), NULL
,
1336 sheet_date_conv (pos
->sheet
));
1341 return value_new_error_VALUE (pos
);
1344 } else if (VALUE_IS_CELLRANGE (b
) || VALUE_IS_ARRAY (b
))
1345 return bin_array_iter_b (pos
, a
, b
,
1346 (BinOpImplicitIteratorFunc
) cb_bin_arith
,
1348 else if (!VALUE_IS_NUMBER (b
)) {
1351 return value_new_error_VALUE (pos
);
1354 res
= bin_arith (expr
, pos
, a
, b
);
1359 case GNM_EXPR_OP_PAREN
:
1360 /* Avoid recursive call to save stack. */
1361 expr
= expr
->unary
.value
;
1364 case GNM_EXPR_OP_PERCENTAGE
:
1365 case GNM_EXPR_OP_UNARY_NEG
:
1366 case GNM_EXPR_OP_UNARY_PLUS
:
1367 /* Guarantees value != NULL */
1368 flags
&= ~GNM_EXPR_EVAL_PERMIT_EMPTY
;
1369 flags
&= ~GNM_EXPR_EVAL_WANT_REF
;
1371 a
= gnm_expr_eval (expr
->unary
.value
, pos
, flags
);
1372 if (VALUE_IS_ERROR (a
))
1374 if (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_UNARY_PLUS
)
1377 /* 2) #!VALUE error if A is not a number */
1378 if (VALUE_IS_STRING (a
)) {
1379 GnmValue
*tmp
= format_match_number (value_peek_string (a
), NULL
,
1380 sheet_date_conv (pos
->sheet
));
1384 return value_new_error_VALUE (pos
);
1386 } else if (VALUE_IS_CELLRANGE (a
) || VALUE_IS_ARRAY (a
)) {
1387 res
= value_new_array_empty (
1388 value_area_get_width (a
, pos
),
1389 value_area_get_height (a
, pos
));
1390 value_area_foreach (a
, pos
, CELL_ITER_ALL
,
1391 (GnmValueIterFunc
) ((GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_UNARY_NEG
)
1392 ? cb_iter_unary_neg
: cb_iter_percentage
),
1397 if (!VALUE_IS_NUMBER (a
))
1398 res
= value_new_error_VALUE (pos
);
1399 else if (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_UNARY_NEG
)
1400 res
= negate_value (a
);
1402 res
= value_new_float (value_get_as_float (a
) / 100);
1403 value_set_fmt (res
, go_format_default_percentage ());
1408 case GNM_EXPR_OP_CAT
:
1409 flags
|= GNM_EXPR_EVAL_PERMIT_EMPTY
;
1410 flags
&= ~GNM_EXPR_EVAL_WANT_REF
;
1411 a
= gnm_expr_eval (expr
->binary
.value_a
, pos
, flags
);
1413 if (VALUE_IS_ERROR (a
))
1415 if (VALUE_IS_CELLRANGE (a
) || VALUE_IS_ARRAY (a
))
1416 return bin_array_iter_a (pos
, a
,
1417 gnm_expr_eval (expr
->binary
.value_b
, pos
, flags
),
1418 (BinOpImplicitIteratorFunc
) cb_bin_cat
,
1421 b
= gnm_expr_eval (expr
->binary
.value_b
, pos
, flags
);
1423 if (VALUE_IS_ERROR (b
)) {
1427 if (VALUE_IS_CELLRANGE (b
) || VALUE_IS_ARRAY (b
))
1428 return bin_array_iter_b (pos
, a
, b
,
1429 (BinOpImplicitIteratorFunc
) cb_bin_cat
,
1435 res
= value_new_string (value_peek_string (b
));
1438 res
= value_new_string ("");
1439 } else if (b
== NULL
) {
1440 res
= value_new_string (value_peek_string (a
));
1443 char *tmp
= g_strconcat (value_peek_string (a
),
1444 value_peek_string (b
), NULL
);
1445 res
= value_new_string_nocopy (tmp
);
1451 case GNM_EXPR_OP_FUNCALL
: {
1454 ei
.func_call
= &expr
->func
;
1456 res
= function_call_with_exprs (&ei
);
1458 return (flags
& GNM_EXPR_EVAL_PERMIT_EMPTY
)
1459 ? NULL
: value_new_int (0);
1460 if (VALUE_IS_CELLRANGE (res
)) {
1462 * pos->dep really shouldn't be NULL here, but it
1463 * will be if someone puts "indirect" into an
1464 * expression used for conditional formats.
1467 dependent_add_dynamic_dep (pos
->dep
,
1468 &res
->v_range
.cell
);
1469 if (!(flags
& GNM_EXPR_EVAL_PERMIT_NON_SCALAR
)) {
1470 res
= value_intersection (res
, pos
);
1471 return (res
!= NULL
)
1472 ? handle_empty (res
, flags
)
1473 : value_new_error_VALUE (pos
);
1477 if (VALUE_IS_ARRAY (res
) &&
1478 !(flags
& GNM_EXPR_EVAL_PERMIT_NON_SCALAR
)) {
1479 a
= (res
->v_array
.x
> 0 && res
->v_array
.y
> 0)
1480 ? value_dup (res
->v_array
.vals
[0][0])
1481 : value_new_error_REF (pos
);
1482 value_release (res
);
1488 case GNM_EXPR_OP_NAME
:
1489 if (expr_name_is_active (expr
->name
.name
))
1490 return handle_empty (expr_name_eval (expr
->name
.name
, pos
, flags
), flags
);
1491 return value_new_error_REF (pos
);
1493 case GNM_EXPR_OP_CELLREF
: {
1497 gnm_cellref_make_abs (&r
, &expr
->cellref
.ref
, pos
);
1499 cell
= sheet_cell_get (eval_sheet (r
.sheet
, pos
->sheet
),
1502 gnm_cell_eval (cell
);
1504 if (flags
& GNM_EXPR_EVAL_WANT_REF
) {
1505 return value_new_cellrange_unsafe (&r
, &r
);
1507 GnmValue
*v
= cell
? value_dup (cell
->value
) : NULL
;
1508 return handle_empty (v
, flags
);
1512 case GNM_EXPR_OP_CONSTANT
:
1513 res
= value_dup (expr
->constant
.value
);
1514 if (VALUE_IS_CELLRANGE (res
) || VALUE_IS_ARRAY (res
)) {
1515 if (flags
& GNM_EXPR_EVAL_PERMIT_NON_SCALAR
)
1517 res
= value_intersection (res
, pos
);
1518 return (res
!= NULL
)
1519 ? handle_empty (res
, flags
)
1520 : value_new_error_VALUE (pos
);
1522 return handle_empty (res
, flags
);
1524 case GNM_EXPR_OP_ARRAY_CORNER
:
1525 case GNM_EXPR_OP_ARRAY_ELEM
:
1526 g_warning ("Unexpected array expressions encountered");
1527 return value_new_error_VALUE (pos
);
1529 case GNM_EXPR_OP_SET
:
1530 if (flags
& GNM_EXPR_EVAL_PERMIT_NON_SCALAR
) {
1532 int argc
= expr
->set
.argc
;
1534 res
= value_new_array_non_init (1, expr
->set
.argc
);
1535 res
->v_array
.vals
[0] = g_new (GnmValue
*, expr
->set
.argc
);
1536 for (i
= 0; i
< argc
; i
++)
1537 res
->v_array
.vals
[0][i
] = gnm_expr_eval (
1538 expr
->set
.argv
[i
], pos
,
1539 GNM_EXPR_EVAL_SCALAR_NON_EMPTY
);
1542 return value_new_error_VALUE (pos
);
1544 case GNM_EXPR_OP_RANGE_CTOR
:
1545 case GNM_EXPR_OP_INTERSECT
:
1546 return gnm_expr_range_op (expr
, pos
, flags
);
1549 g_assert_not_reached ();
1550 return value_new_error (pos
, _("Unknown evaluation error"));
1555 gnm_expr_simplify_if (GnmExpr
const *expr
)
1557 static GnmFunc
*f_if
= NULL
;
1558 GnmExpr
const *cond
;
1561 g_return_val_if_fail (expr
!= NULL
, NULL
);
1563 if (GNM_EXPR_GET_OPER (expr
) != GNM_EXPR_OP_FUNCALL
)
1567 f_if
= gnm_func_lookup ("if", NULL
);
1569 if (expr
->func
.func
!= f_if
|| expr
->func
.argc
!= 3)
1572 cond
= expr
->func
.argv
[0];
1573 if (GNM_EXPR_GET_OPER (cond
) == GNM_EXPR_OP_CONSTANT
) {
1574 GnmValue
const *condval
= cond
->constant
.value
;
1576 c
= value_get_as_bool (condval
, &err
);
1582 // We used to test for true() and false() as conditions too, but the code
1583 // never worked and has been unreachable until now.
1585 return gnm_expr_copy (expr
->func
.argv
[c
? 1 : 2]);
1591 * Converts a parsed tree into its string representation
1592 * assuming that we are evaluating at col, row
1594 * This routine is pretty simple: it walks the GnmExpr and
1595 * appends a string representation to the target.
1598 do_expr_as_string (GnmExpr
const *expr
, int paren_level
,
1599 GnmConventionsOut
*out
)
1603 guint8 prec
; /* Precedences -- should match parser.y */
1604 guint8 assoc_left
, assoc_right
; /* 0: no, 1: yes. */
1605 guint8 is_prefix
; /* for unary operators */
1606 } const operations
[] = {
1607 { "", 0, 0, 0, 0 }, /* Parentheses for clarity */
1608 { "=", 1, 1, 0, 0 },
1609 { ">", 1, 1, 0, 0 },
1610 { "<", 1, 1, 0, 0 },
1611 { ">=", 1, 1, 0, 0 },
1612 { "<=", 1, 1, 0, 0 },
1613 { "<>", 1, 1, 0, 0 },
1614 { "+", 3, 1, 0, 0 },
1615 { "-", 3, 1, 0, 0 },
1616 { "*", 4, 1, 0, 0 },
1617 { "/", 4, 1, 0, 0 },
1618 { "^", 5, 0, 0, 0 }, /* Note: neither left nor right */
1619 { "&", 2, 1, 0, 0 },
1620 { "", 0, 0, 0, 0 }, /* Funcall */
1621 { "", 0, 0, 0, 0 }, /* Name */
1622 { "", 0, 0, 0, 0 }, /* Constant */
1623 { "", 0, 0, 0, 0 }, /* Var */
1624 { "-", 7, 0, 0, 1 }, /* Unary - */
1625 { "+", 7, 0, 0, 1 }, /* Unary + */
1626 { "%", 6, 0, 0, 0 }, /* Percentage (NOT MODULO) */
1627 { "", 0, 0, 0, 0 }, /* ArrayCorner */
1628 { "", 0, 0, 0, 0 }, /* ArrayElem */
1629 { "", 8, 0, 0, 0 }, /* Set */
1630 { ":", 10, 1, 0, 0 }, /* Range Ctor */
1631 { " ", 9, 1, 0, 0 } /* Intersection */
1633 GnmExprOp
const op
= GNM_EXPR_GET_OPER (expr
);
1634 GString
*target
= out
->accum
;
1637 case GNM_EXPR_OP_RANGE_CTOR
:
1638 case GNM_EXPR_OP_INTERSECT
:
1639 case GNM_EXPR_OP_ANY_BINARY
: {
1640 char const *opname
= operations
[op
].name
;
1641 int prec
= operations
[op
].prec
;
1642 gboolean need_par
= (prec
<= paren_level
);
1643 size_t prelen
= target
->len
;
1645 if (need_par
) g_string_append_c (target
, '(');
1646 do_expr_as_string (expr
->binary
.value_a
,
1647 prec
- operations
[op
].assoc_left
, out
);
1650 * Avoid getting "-2^2". We want to make sure files do not
1651 * contain that construct as we might later change precedence.
1653 * Always produce either "-(2^2)" or "(-2)^2".
1655 * Note, that the parser introduces an explicit parenthesis in
1656 * this case also, so parsed expressions should not be
1657 * affected by the code here.
1659 if (op
== GNM_EXPR_OP_EXP
&&
1660 (target
->str
[prelen
] == '-' || target
->str
[prelen
] == '+')) {
1661 g_string_insert_c (target
, prelen
, '(');
1662 g_string_append_c (target
, ')');
1665 /* Instead of this we ought to move the whole operations
1666 table into the conventions. */
1667 if (op
== GNM_EXPR_OP_INTERSECT
)
1668 g_string_append_unichar (target
, out
->convs
->intersection_char
);
1670 g_string_append (target
, opname
);
1672 do_expr_as_string (expr
->binary
.value_b
,
1673 prec
- operations
[op
].assoc_right
, out
);
1674 if (need_par
) g_string_append_c (target
, ')');
1678 case GNM_EXPR_OP_ANY_UNARY
: {
1679 char const *opname
= operations
[op
].name
;
1680 int prec
= operations
[op
].prec
;
1681 gboolean is_prefix
= operations
[op
].is_prefix
;
1682 gboolean need_par
= (prec
<= paren_level
);
1684 if (need_par
) g_string_append_c (target
, '(');
1685 if (is_prefix
) g_string_append (target
, opname
);
1686 do_expr_as_string (expr
->unary
.value
, prec
, out
);
1687 if (!is_prefix
) g_string_append (target
, opname
);
1688 if (need_par
) g_string_append_c (target
, ')');
1692 case GNM_EXPR_OP_FUNCALL
:
1693 out
->convs
->output
.func (out
, &expr
->func
);
1696 case GNM_EXPR_OP_NAME
:
1697 out
->convs
->output
.name (out
, &expr
->name
);
1700 case GNM_EXPR_OP_CELLREF
:
1701 out
->convs
->output
.cell_ref (out
, &expr
->cellref
.ref
, FALSE
);
1704 case GNM_EXPR_OP_CONSTANT
: {
1705 GnmValue
const *v
= expr
->constant
.value
;
1706 size_t prelen
= target
->len
;
1708 if (VALUE_IS_STRING (v
)) {
1709 out
->convs
->output
.string (out
, v
->v_str
.val
);
1713 if (VALUE_IS_CELLRANGE (v
)) {
1714 out
->convs
->output
.range_ref (out
, &v
->v_range
.cell
);
1718 if (VALUE_IS_BOOLEAN (v
) &&
1719 out
->convs
->output
.boolean
!= NULL
) {
1720 out
->convs
->output
.boolean (out
, v
->v_bool
.val
);
1725 value_get_as_gstring (v
, target
, out
->convs
);
1727 /* If the number has a sign, pretend that it is the result of
1728 * OPER_UNARY_{NEG,PLUS}.
1730 if ((target
->str
[prelen
] == '-' || target
->str
[prelen
] == '+') &&
1731 operations
[GNM_EXPR_OP_UNARY_NEG
].prec
<= paren_level
) {
1732 g_string_insert_c (target
, prelen
, '(');
1733 g_string_append_c (target
, ')');
1738 case GNM_EXPR_OP_ARRAY_CORNER
:
1739 do_expr_as_string (expr
->array_corner
.expr
, 0, out
);
1742 case GNM_EXPR_OP_ARRAY_ELEM
: {
1743 GnmCell
const *corner
= array_elem_get_corner (&expr
->array_elem
,
1744 out
->pp
->sheet
, &out
->pp
->eval
);
1745 if (NULL
!= corner
) {
1746 GnmParsePos
const *real_pp
= out
->pp
;
1747 GnmParsePos pp
= *real_pp
;
1749 pp
.eval
.col
-= expr
->array_elem
.x
;
1750 pp
.eval
.row
-= expr
->array_elem
.y
;
1753 corner
->base
.texpr
->expr
->array_corner
.expr
,
1761 case GNM_EXPR_OP_SET
:
1762 gnm_expr_list_as_string (expr
->set
.argc
, expr
->set
.argv
, out
);
1766 g_string_append (target
, "<ERROR>");
1770 gnm_expr_as_gstring (GnmExpr
const *expr
, GnmConventionsOut
*out
)
1772 g_return_if_fail (expr
!= NULL
);
1773 g_return_if_fail (out
!= NULL
);
1775 do_expr_as_string (expr
, 0, out
);
1779 gnm_expr_as_string (GnmExpr
const *expr
, GnmParsePos
const *pp
,
1780 GnmConventions
const *convs
)
1782 GnmConventionsOut out
;
1785 g_return_val_if_fail (expr
!= NULL
, NULL
);
1788 * Defaults for debugging only!
1791 /* UGH: Just get the first sheet in the first workbook! */
1792 Workbook
*wb
= gnm_app_workbook_get_by_index (0);
1793 Sheet
*sheet
= workbook_sheet_by_index (wb
, 0);
1794 parse_pos_init (&pp0
, NULL
, sheet
, 0, 0);
1799 ? sheet_get_conventions (pp
->sheet
)
1800 : gnm_conventions_default
;
1802 out
.accum
= g_string_new (NULL
);
1805 do_expr_as_string (expr
, 0, &out
);
1806 return g_string_free (out
.accum
, FALSE
);
1809 /****************************************************************************/
1812 gnm_expr_is_err (GnmExpr
const *expr
, GnmStdError err
)
1816 if (GNM_EXPR_GET_OPER (expr
) != GNM_EXPR_OP_CONSTANT
)
1819 err2
= value_error_classify (expr
->constant
.value
);
1824 * gnm_expr_get_constant:
1827 * If this expression consists of just a constant, return it.
1830 gnm_expr_get_constant (GnmExpr
const *expr
)
1832 if (GNM_EXPR_GET_OPER (expr
) != GNM_EXPR_OP_CONSTANT
)
1835 return expr
->constant
.value
;
1839 * gnm_expr_get_name:
1842 * If this expression consists of just a name, return it.
1844 GnmNamedExpr
const *
1845 gnm_expr_get_name (GnmExpr
const *expr
)
1847 if (GNM_EXPR_GET_OPER (expr
) != GNM_EXPR_OP_NAME
)
1850 return expr
->name
.name
;
1855 * gnm_expr_get_cellref:
1858 * If this expression consists of just a cell reference, return it.
1861 gnm_expr_get_cellref (GnmExpr
const *expr
)
1863 if (GNM_EXPR_GET_OPER (expr
) != GNM_EXPR_OP_CELLREF
)
1866 return &expr
->cellref
.ref
;
1871 GnmExprRelocateInfo
const *details
;
1872 gboolean from_inside
;
1873 gboolean check_rels
;
1874 } RelocInfoInternal
;
1876 static GnmExpr
const *
1877 invalidate_sheet_cellrange (RelocInfoInternal
const *rinfo
,
1878 GnmValueRange
const *v
)
1880 GnmCellRef ref_a
= v
->cell
.a
;
1881 GnmCellRef ref_b
= v
->cell
.b
;
1883 Sheet
const *sheet_a
= ref_a
.sheet
;
1884 Sheet
const *sheet_b
= ref_b
.sheet
;
1886 gboolean hit_a
= sheet_a
&& sheet_a
->being_invalidated
;
1887 gboolean hit_b
= sheet_b
&& sheet_b
->being_invalidated
;
1890 if (!hit_a
&& !hit_b
)
1893 if (sheet_a
== NULL
|| sheet_b
== NULL
||
1894 sheet_a
->workbook
!= sheet_b
->workbook
)
1895 /* A 3D reference between workbooks? */
1896 return gnm_expr_new_constant (value_new_error_REF (NULL
));
1898 /* Narrow the sheet range. */
1899 wb
= sheet_a
->workbook
;
1900 dir
= (sheet_a
->index_in_wb
< sheet_b
->index_in_wb
) ? +1 : -1;
1901 while (sheet_a
!= sheet_b
&& sheet_a
->being_invalidated
)
1902 sheet_a
= workbook_sheet_by_index (wb
, sheet_a
->index_in_wb
+ dir
);
1903 while (sheet_a
!= sheet_b
&& sheet_b
->being_invalidated
)
1904 sheet_b
= workbook_sheet_by_index (wb
, sheet_b
->index_in_wb
- dir
);
1906 if (sheet_a
->being_invalidated
)
1907 return gnm_expr_new_constant (value_new_error_REF (NULL
));
1909 ref_a
.sheet
= (Sheet
*)sheet_a
;
1910 ref_b
.sheet
= (Sheet
*)sheet_b
;
1911 return gnm_expr_new_constant (value_new_cellrange_unsafe (&ref_a
, &ref_b
));
1915 reloc_range (GnmExprRelocateInfo
const *rinfo
,
1916 Sheet
const *start_sheet
, Sheet
const *end_sheet
,
1919 GnmRange t
, b
, l
, r
;
1920 gboolean start
, end
;
1922 if (start_sheet
!= end_sheet
|| /* ignore 3d refs */
1923 start_sheet
!= rinfo
->origin_sheet
) /* ref is to a different sheet */
1926 t
.start
.col
= b
.start
.col
= l
.start
.col
= l
.end
.col
= rng
->start
.col
;
1927 t
.end
.col
= b
.end
.col
= r
.start
.col
= r
.end
.col
= rng
->end
.col
;
1928 t
.start
.row
= t
.end
.row
= l
.start
.row
= r
.start
.row
= rng
->start
.row
;
1929 b
.start
.row
= b
.end
.row
= l
.end
.row
= r
.end
.row
= rng
->end
.row
;
1931 start
= range_contained (&t
, &rinfo
->origin
);
1932 end
= range_contained (&b
, &rinfo
->origin
);
1933 if (start
&& end
) { /* full enclosure */
1934 rng
->start
.col
+= rinfo
->col_offset
;
1935 rng
->end
.col
+= rinfo
->col_offset
;
1936 rng
->start
.row
+= rinfo
->row_offset
;
1937 rng
->end
.row
+= rinfo
->row_offset
;
1941 if (rinfo
->col_offset
== 0) {
1942 if (start
&& rinfo
->row_offset
< range_height (rng
)) {
1943 rng
->start
.row
+= rinfo
->row_offset
;
1946 if (end
&& rinfo
->row_offset
> -range_height (rng
)) {
1947 /* Special case invalidating the bottom of a range while
1948 * deleting rows. Otherwise we #REF! before we can shorten
1949 * The -1 is safe, origin.start.row == 0 is handled above */
1950 if (rinfo
->reloc_type
== GNM_EXPR_RELOCATE_ROWS
&&
1951 rinfo
->row_offset
>= gnm_sheet_get_max_rows (end_sheet
))
1952 rng
->end
.row
= rinfo
->origin
.start
.row
- 1;
1954 rng
->end
.row
+= rinfo
->row_offset
;
1959 if (rinfo
->row_offset
== 0) {
1960 if (range_contained (&l
, &rinfo
->origin
) &&
1961 rinfo
->col_offset
< range_width (rng
)) {
1962 rng
->start
.col
+= rinfo
->col_offset
;
1965 if (range_contained (&r
, &rinfo
->origin
) &&
1966 rinfo
->col_offset
> -range_width (rng
)) {
1967 /* Special case invalidating the right side of a range while
1968 * deleting cols. Otherwise we #REF! before we can shorten.
1969 * The -1 is safe, origin.start.col == 0 is handled above */
1970 if (rinfo
->reloc_type
== GNM_EXPR_RELOCATE_COLS
&&
1971 rinfo
->col_offset
>= gnm_sheet_get_max_cols (end_sheet
))
1972 rng
->end
.col
= rinfo
->origin
.start
.col
- 1;
1974 rng
->end
.col
+= rinfo
->col_offset
;
1983 reloc_normalize_cellref (RelocInfoInternal
const *rinfo
, GnmCellRef
const *ref
,
1984 Sheet
**sheet
, GnmCellPos
*res
)
1986 *sheet
= eval_sheet (ref
->sheet
, rinfo
->details
->pos
.sheet
);
1987 res
->col
= ref
->col
;
1988 if (ref
->col_relative
) {
1989 if (rinfo
->check_rels
)
1990 res
->col
+= rinfo
->details
->pos
.eval
.col
;
1994 res
->row
= ref
->row
;
1995 if (ref
->row_relative
) {
1996 if (rinfo
->check_rels
)
1997 res
->row
+= rinfo
->details
->pos
.eval
.row
;
2003 /* Return TRUE if @pos is out of bounds */
2005 reloc_restore_cellref (RelocInfoInternal
const *rinfo
,
2006 GnmSheetSize
const *ss
, GnmCellPos
const *pos
,
2009 if (res
->sheet
== rinfo
->details
->origin_sheet
) {
2010 res
->sheet
= rinfo
->details
->target_sheet
;
2012 ss
= gnm_sheet_get_size (res
->sheet
);
2015 if (!res
->col_relative
|| rinfo
->check_rels
) {
2016 if (pos
->col
< 0 || ss
->max_cols
<= pos
->col
)
2018 res
->col
= pos
->col
;
2019 if (res
->col_relative
) {
2020 res
->col
-= rinfo
->details
->pos
.eval
.col
;
2021 if (rinfo
->from_inside
)
2022 res
->col
-= rinfo
->details
->col_offset
;
2026 if (!res
->row_relative
|| rinfo
->check_rels
) {
2027 if (pos
->row
< 0 || ss
->max_rows
<= pos
->row
)
2029 res
->row
= pos
->row
;
2030 if (res
->row_relative
) {
2031 res
->row
-= rinfo
->details
->pos
.eval
.row
;
2032 if (rinfo
->from_inside
)
2033 res
->row
-= rinfo
->details
->row_offset
;
2041 static GnmExpr
const *
2042 reloc_cellrange (RelocInfoInternal
const *rinfo
, GnmValueRange
const *v
,
2043 gboolean sticky_end
)
2046 Sheet
*start_sheet
, *end_sheet
;
2047 GnmSheetSize
const *start_ss
, *end_ss
;
2048 gboolean full_col
, full_row
;
2049 gboolean full_col_begin
, full_row_begin
;
2051 /* Normalize the rangeRef, and remember if we had a full col/row
2052 * ref. If relocating the result changes things, or if we're from
2053 * inside the range that is moving map back to a RangeRef from the
2054 * target position. If the result is different that the original
2055 * generate a new expression. */
2056 reloc_normalize_cellref (rinfo
, &v
->cell
.a
, &start_sheet
, &r
.start
);
2057 reloc_normalize_cellref (rinfo
, &v
->cell
.b
, &end_sheet
, &r
.end
);
2058 /* (Foo,NULL) in Bar will generate (Foo,Bar) in normalize */
2059 if (NULL
== v
->cell
.b
.sheet
)
2060 end_sheet
= start_sheet
;
2061 start_ss
= gnm_sheet_get_size2 (start_sheet
, rinfo
->details
->pos
.wb
);
2062 end_ss
= gnm_sheet_get_size2 (end_sheet
, rinfo
->details
->pos
.wb
);
2064 full_col
= sticky_end
&& r
.end
.row
>= start_ss
->max_rows
- 1;
2065 full_col_begin
= full_col
&& r
.start
.row
== 0;
2067 full_row
= sticky_end
&& r
.end
.col
>= start_ss
->max_cols
- 1;
2068 full_row_begin
= full_row
&& r
.start
.col
== 0;
2070 if (reloc_range (rinfo
->details
, start_sheet
, end_sheet
, &r
) ||
2071 rinfo
->from_inside
) {
2072 GnmRangeRef res
= v
->cell
;
2075 r
.end
.row
= start_ss
->max_rows
- 1;
2079 r
.end
.col
= start_ss
->max_cols
- 1;
2083 if (reloc_restore_cellref (rinfo
, start_ss
, &r
.start
, &res
.a
) ||
2084 reloc_restore_cellref (rinfo
, end_ss
, &r
.end
, &res
.b
))
2085 return gnm_expr_new_constant (value_new_error_REF (NULL
));
2086 if (gnm_rangeref_equal (&res
, &v
->cell
))
2088 return gnm_expr_new_constant (value_new_cellrange_unsafe (&res
.a
, &res
.b
));
2094 static GnmExpr
const *
2095 gnm_expr_relocate (GnmExpr
const *expr
, RelocInfoInternal
const *rinfo
);
2097 static GnmExpr
const *
2098 cb_relocate (GnmExpr
const *expr
, GnmExprWalk
*data
)
2100 RelocInfoInternal
const *rinfo
= data
->user
;
2102 switch (GNM_EXPR_GET_OPER (expr
)) {
2103 case GNM_EXPR_OP_NAME
: {
2104 GnmNamedExpr
*nexpr
= expr
->name
.name
;
2106 /* we cannot invalidate references to the name that are
2107 * sitting in the undo queue, or the clipboard. So we just
2108 * flag the name as inactive and remove the reference here.
2110 if (!expr_name_is_active (nexpr
))
2111 return gnm_expr_new_constant (value_new_error_REF (NULL
));
2113 switch (rinfo
->details
->reloc_type
) {
2114 case GNM_EXPR_RELOCATE_INVALIDATE_SHEET
:
2115 if (nexpr
->pos
.sheet
&& nexpr
->pos
.sheet
->being_invalidated
)
2116 return gnm_expr_new_constant (value_new_error_REF (NULL
));
2120 case GNM_EXPR_RELOCATE_MOVE_RANGE
:
2122 * If the name is not officially scoped, check
2123 * that it is available in the new scope
2125 if (expr
->name
.optional_scope
== NULL
&&
2126 rinfo
->details
->target_sheet
!= rinfo
->details
->origin_sheet
) {
2127 GnmNamedExpr
*new_nexpr
;
2129 parse_pos_init_sheet (&pos
, rinfo
->details
->target_sheet
);
2131 /* If the name is not available in the new scope explicitly scope it */
2132 new_nexpr
= expr_name_lookup (&pos
, expr_name_name (nexpr
));
2133 if (new_nexpr
== NULL
) {
2134 if (nexpr
->pos
.sheet
!= NULL
)
2135 return gnm_expr_new_name (nexpr
, nexpr
->pos
.sheet
, NULL
);
2136 return gnm_expr_new_name (nexpr
, NULL
, nexpr
->pos
.wb
);
2139 /* replace it with the new name using qualified as
2140 * local to the target sheet
2142 return gnm_expr_new_name (new_nexpr
, pos
.sheet
, NULL
);
2145 * Do NOT rewrite the name.
2147 * Just invalidate the use of the name if the
2148 * name's expression, if relocated, would
2151 GnmExpr
const *tmp
=
2152 gnm_expr_relocate (nexpr
->texpr
->expr
,
2154 if (tmp
&& gnm_expr_is_err (tmp
, GNM_ERROR_REF
))
2158 gnm_expr_free (tmp
);
2163 case GNM_EXPR_RELOCATE_COLS
:
2164 case GNM_EXPR_RELOCATE_ROWS
:
2168 g_assert_not_reached ();
2172 case GNM_EXPR_OP_CELLREF
: {
2173 GnmCellRef
const *ref
= &expr
->cellref
.ref
;
2174 switch (rinfo
->details
->reloc_type
) {
2175 case GNM_EXPR_RELOCATE_INVALIDATE_SHEET
:
2177 ref
->sheet
->being_invalidated
)
2178 return gnm_expr_new_constant (value_new_error_REF (NULL
));
2181 case GNM_EXPR_RELOCATE_MOVE_RANGE
:
2182 case GNM_EXPR_RELOCATE_COLS
:
2183 case GNM_EXPR_RELOCATE_ROWS
: {
2186 GnmSheetSize
const *ss
;
2188 reloc_normalize_cellref (rinfo
, ref
, &sheet
, &r
.start
);
2190 ss
= gnm_sheet_get_size2 (sheet
, rinfo
->details
->pos
.wb
);
2192 if (reloc_range (rinfo
->details
, sheet
, sheet
, &r
) ||
2193 rinfo
->from_inside
) {
2194 GnmCellRef res
= *ref
;
2195 if (reloc_restore_cellref (rinfo
, ss
, &r
.start
, &res
))
2196 return gnm_expr_new_constant (value_new_error_REF (NULL
));
2197 if (gnm_cellref_equal (&res
, ref
))
2199 return gnm_expr_new_cellref (&res
);
2205 g_assert_not_reached ();
2211 case GNM_EXPR_OP_CONSTANT
:
2212 if (VALUE_IS_CELLRANGE (expr
->constant
.value
)) {
2213 GnmValueRange
const *vr
= &expr
->constant
.value
->v_range
;
2214 switch (rinfo
->details
->reloc_type
) {
2215 case GNM_EXPR_RELOCATE_INVALIDATE_SHEET
:
2216 return invalidate_sheet_cellrange (rinfo
, vr
);
2217 case GNM_EXPR_RELOCATE_MOVE_RANGE
:
2218 return reloc_cellrange (rinfo
, vr
, TRUE
);
2219 case GNM_EXPR_RELOCATE_COLS
:
2220 case GNM_EXPR_RELOCATE_ROWS
:
2221 return reloc_cellrange (rinfo
, vr
, rinfo
->details
->sticky_end
);
2223 g_assert_not_reached ();
2233 static GnmExpr
const *
2234 gnm_expr_relocate (GnmExpr
const *expr
, RelocInfoInternal
const *rinfo
)
2236 g_return_val_if_fail (expr
!= NULL
, NULL
);
2237 return gnm_expr_walk (expr
, cb_relocate
, (gpointer
)rinfo
);
2241 gnm_expr_get_func_def (GnmExpr
const *expr
)
2243 g_return_val_if_fail (expr
!= NULL
, NULL
);
2244 g_return_val_if_fail (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_FUNCALL
, NULL
);
2246 return expr
->func
.func
;
2250 gnm_expr_get_func_arg (GnmExpr
const *expr
, int i
)
2252 g_return_val_if_fail (expr
!= NULL
, NULL
);
2253 g_return_val_if_fail (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_FUNCALL
, NULL
);
2254 g_return_val_if_fail (i
>= 0 && i
< expr
->func
.argc
, NULL
);
2256 return expr
->func
.argv
[i
];
2261 cellref_boundingbox (GnmCellRef
const *cr
, Sheet
const *sheet
, GnmRange
*bound
)
2263 GnmSheetSize
const *ss
;
2267 ss
= gnm_sheet_get_size (sheet
);
2269 if (cr
->col_relative
) {
2271 int const c
= ss
->max_cols
- cr
->col
- 1;
2272 if (bound
->end
.col
> c
)
2275 int const c
= -cr
->col
;
2276 if (bound
->start
.col
< c
)
2277 bound
->start
.col
= c
;
2280 if (cr
->row_relative
) {
2282 int const r
= ss
->max_rows
- cr
->row
- 1;
2283 if (bound
->end
.row
> r
)
2286 int const r
= -cr
->row
;
2287 if (bound
->start
.row
< r
)
2288 bound
->start
.row
= r
;
2293 static GnmExpr
const *
2294 cb_contains_subtotal (GnmExpr
const *expr
, GnmExprWalk
*data
)
2296 gboolean
*res
= data
->user
;
2297 if (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_FUNCALL
&&
2298 strcmp (expr
->func
.func
->name
, "subtotal") == 0) {
2306 * gnm_expr_containts_subtotal:
2309 * return TRUE if the expression calls the SUBTOTAL function
2312 gnm_expr_contains_subtotal (GnmExpr
const *expr
)
2314 gboolean res
= FALSE
;
2315 gnm_expr_walk (expr
, cb_contains_subtotal
, &res
);
2320 * gnm_expr_get_range:
2323 * If this expression contains a single range return it.
2324 * Caller is responsible for value_releasing the result.
2327 gnm_expr_get_range (GnmExpr
const *expr
)
2329 g_return_val_if_fail (expr
!= NULL
, NULL
);
2331 switch (GNM_EXPR_GET_OPER (expr
)) {
2332 case GNM_EXPR_OP_CELLREF
:
2333 return value_new_cellrange_unsafe (
2334 &expr
->cellref
.ref
, &expr
->cellref
.ref
);
2336 case GNM_EXPR_OP_CONSTANT
:
2337 if (VALUE_IS_CELLRANGE (expr
->constant
.value
))
2338 return value_dup (expr
->constant
.value
);
2341 case GNM_EXPR_OP_NAME
:
2342 if (!expr_name_is_active (expr
->name
.name
))
2344 return gnm_expr_top_get_range (expr
->name
.name
->texpr
);
2346 case GNM_EXPR_OP_PAREN
:
2347 return gnm_expr_get_range (expr
->unary
.value
);
2355 gnm_insert_unique_value_cmp (gconstpointer a
, gconstpointer b
)
2357 return (value_equal (a
,b
) ? 0 : 1);
2363 gnm_insert_unique_value (GSList
*list
, GnmValue
*data
)
2365 if (g_slist_find_custom (list
, data
,
2366 gnm_insert_unique_value_cmp
)
2368 return g_slist_prepend (list
, data
);
2369 value_release (data
);
2374 * gnm_expr_is_rangeref:
2377 * Returns TRUE if the expression can generate a reference.
2378 * NOTE : in the future it would be nice to know if a function
2379 * can return a reference to tighten that up a bit.
2382 gnm_expr_is_rangeref (GnmExpr
const *expr
)
2384 g_return_val_if_fail (expr
!= NULL
, FALSE
);
2386 switch (GNM_EXPR_GET_OPER (expr
)) {
2387 /* would be better if we could differential which functions can return refs */
2388 case GNM_EXPR_OP_FUNCALL
:
2390 /* a set in a set, do we need this ? */
2391 case GNM_EXPR_OP_SET
:
2393 case GNM_EXPR_OP_RANGE_CTOR
:
2394 case GNM_EXPR_OP_INTERSECT
:
2395 case GNM_EXPR_OP_CELLREF
:
2398 case GNM_EXPR_OP_CONSTANT
:
2399 if (VALUE_IS_CELLRANGE (expr
->constant
.value
))
2403 case GNM_EXPR_OP_NAME
:
2404 if (expr_name_is_active (expr
->name
.name
))
2405 return gnm_expr_is_rangeref (expr
->name
.name
->texpr
->expr
);
2408 case GNM_EXPR_OP_ARRAY_CORNER
: /* I don't think this is possible */
2409 case GNM_EXPR_OP_ARRAY_ELEM
:
2416 gnm_expr_is_data_table (GnmExpr
const *expr
, GnmCellPos
*c_in
, GnmCellPos
*r_in
)
2418 if (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_FUNCALL
) {
2419 char const *name
= gnm_func_get_name (expr
->func
.func
, FALSE
);
2420 if (name
&& 0 == strcmp (name
, "table")) {
2422 GnmExpr
const *r
= (expr
->func
.argc
<= 0)
2424 : expr
->func
.argv
[0];
2426 if (r
!= NULL
&& GNM_EXPR_GET_OPER (r
) == GNM_EXPR_OP_CELLREF
) {
2427 r_in
->col
= r
->cellref
.ref
.col
;
2428 r_in
->row
= r
->cellref
.ref
.row
;
2430 r_in
->col
= r_in
->row
= 0; /* impossible */
2433 GnmExpr
const *c
= (expr
->func
.argc
<= 1)
2435 : expr
->func
.argv
[1];
2437 if (c
!= NULL
&& GNM_EXPR_GET_OPER (c
) == GNM_EXPR_OP_CELLREF
) {
2438 c_in
->col
= c
->cellref
.ref
.col
;
2439 c_in
->row
= c
->cellref
.ref
.row
;
2441 c_in
->col
= c_in
->row
= 0; /* impossible */
2447 /* Do we need anything else here ? */
2452 static GnmExpr
const *
2453 do_expr_walk (GnmExpr
const *expr
, GnmExprWalkerFunc walker
, GnmExprWalk
*data
)
2457 res
= walker (expr
, data
);
2459 if (res
) gnm_expr_free (res
);
2465 switch (GNM_EXPR_GET_OPER (expr
)) {
2466 case GNM_EXPR_OP_RANGE_CTOR
:
2467 case GNM_EXPR_OP_INTERSECT
:
2468 case GNM_EXPR_OP_ANY_BINARY
: {
2469 GnmExpr
const *a
, *b
;
2471 a
= do_expr_walk (expr
->binary
.value_a
, walker
, data
);
2475 b
= do_expr_walk (expr
->binary
.value_b
, walker
, data
);
2477 if (a
) gnm_expr_free (a
);
2485 a
= gnm_expr_copy (expr
->binary
.value_a
);
2487 b
= gnm_expr_copy (expr
->binary
.value_b
);
2489 return gnm_expr_new_binary (a
, GNM_EXPR_GET_OPER (expr
), b
);
2492 case GNM_EXPR_OP_ANY_UNARY
: {
2493 GnmExpr
const *a
= do_expr_walk (expr
->unary
.value
, walker
, data
);
2495 ? gnm_expr_new_unary (GNM_EXPR_GET_OPER (expr
), a
)
2499 case GNM_EXPR_OP_FUNCALL
: {
2500 gboolean any
= FALSE
;
2502 int argc
= expr
->func
.argc
;
2503 GnmExprConstPtr
*argv
=
2504 argc
? g_new (GnmExprConstPtr
, argc
) : NULL
;
2506 for (i
= 0; i
< argc
; i
++) {
2507 argv
[i
] = do_expr_walk (expr
->func
.argv
[i
], walker
, data
);
2511 gnm_expr_free (argv
[i
]);
2521 for (i
= 0; i
< argc
; i
++)
2523 argv
[i
] = gnm_expr_copy (expr
->func
.argv
[i
]);
2524 return gnm_expr_new_funcallv (expr
->func
.func
,
2531 case GNM_EXPR_OP_SET
: {
2532 gboolean any
= FALSE
;
2534 int argc
= expr
->set
.argc
;
2535 GnmExprConstPtr
*argv
=
2536 argc
? g_new (GnmExprConstPtr
, argc
) : NULL
;
2538 for (i
= 0; i
< argc
; i
++) {
2539 argv
[i
] = do_expr_walk (expr
->set
.argv
[i
], walker
, data
);
2543 gnm_expr_free (argv
[i
]);
2553 for (i
= 0; i
< argc
; i
++)
2555 argv
[i
] = gnm_expr_copy (expr
->set
.argv
[i
]);
2556 return gnm_expr_new_setv (argc
, argv
);
2563 case GNM_EXPR_OP_ARRAY_CORNER
: {
2564 GnmExpr
const *e
= do_expr_walk (expr
->array_corner
.expr
, walker
, data
);
2566 ? gnm_expr_new_array_corner (
2567 expr
->array_corner
.cols
,
2568 expr
->array_corner
.rows
, e
)
2579 * @expr: expression to walk
2580 * @walker: (scope call): callback for each sub-expression
2581 * @user: user data pointer
2583 * Returns: (transfer full) (allow-none): transformed expression.
2585 * This function walks the expression and calls the walker function for
2586 * each subexpression. If the walker returns a non-NULL expression,
2587 * a new expression is built.
2589 * The walker will be called for an expression before its subexpressions.
2590 * It will receive the expression as its first argument and a GnmExprWalk
2591 * pointer as its second. It may set the stop flag to terminate the walk
2592 * in which case gnm_expr_walk will return NULL.
2595 gnm_expr_walk (GnmExpr
const *expr
, GnmExprWalkerFunc walker
, gpointer user
)
2599 g_return_val_if_fail (expr
!= NULL
, NULL
);
2604 return do_expr_walk (expr
, walker
, &data
);
2608 gnm_expr_is_empty (GnmExpr
const *expr
)
2610 g_return_val_if_fail (expr
!= NULL
, FALSE
);
2612 return (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_CONSTANT
&&
2613 VALUE_IS_EMPTY (expr
->constant
.value
));
2617 * This frees the data pointers and the list.
2620 gnm_expr_list_unref (GnmExprList
*list
)
2623 for (l
= list
; l
; l
= l
->next
)
2624 gnm_expr_free (l
->data
);
2625 gnm_expr_list_free (list
);
2629 * gnm_expr_list_copy:
2630 * @list: list of expressions
2632 * Returns: (transfer full): a copy of the list.
2635 gnm_expr_list_copy (GnmExprList
*list
)
2637 GnmExprList
*res
= g_slist_copy (list
); /* shallow */
2640 for (l
= res
; l
; l
= l
->next
)
2641 l
->data
= (GnmExpr
*) gnm_expr_copy (l
->data
);
2648 gnm_expr_list_as_string (int argc
,
2649 GnmExprConstPtr
const *argv
,
2650 GnmConventionsOut
*out
)
2654 if (out
->convs
->arg_sep
)
2655 arg_sep
= out
->convs
->arg_sep
;
2657 arg_sep
= go_locale_get_arg_sep ();
2659 g_string_append_c (out
->accum
, '(');
2660 for (i
= 0; i
< argc
; i
++) {
2662 g_string_append_unichar (out
->accum
, arg_sep
);
2663 do_expr_as_string (argv
[i
], 0, out
);
2665 g_string_append_c (out
->accum
, ')');
2669 gnm_expr_hash (GnmExpr
const *expr
)
2671 guint h
= (guint
)(GNM_EXPR_GET_OPER (expr
));
2673 switch (GNM_EXPR_GET_OPER (expr
)){
2674 case GNM_EXPR_OP_INTERSECT
:
2675 case GNM_EXPR_OP_RANGE_CTOR
:
2676 case GNM_EXPR_OP_ANY_BINARY
:
2677 return ((gnm_expr_hash (expr
->binary
.value_a
) * 7) ^
2678 (gnm_expr_hash (expr
->binary
.value_b
) * 3) ^
2681 case GNM_EXPR_OP_ANY_UNARY
:
2682 return ((gnm_expr_hash (expr
->unary
.value
) * 7) ^
2685 case GNM_EXPR_OP_FUNCALL
: {
2687 for (i
= 0; i
< expr
->func
.argc
; i
++)
2688 h
= (h
* 3) ^ gnm_expr_hash (expr
->func
.argv
[i
]);
2692 case GNM_EXPR_OP_SET
: {
2694 for (i
= 0; i
< expr
->set
.argc
; i
++)
2695 h
= (h
* 3) ^ gnm_expr_hash (expr
->set
.argv
[i
]);
2699 case GNM_EXPR_OP_CONSTANT
:
2700 return value_hash (expr
->constant
.value
);
2702 case GNM_EXPR_OP_NAME
:
2703 /* all we need is a somewhat unique hash, ignore int != ptr */
2704 return GPOINTER_TO_UINT (expr
->name
.name
);
2706 case GNM_EXPR_OP_CELLREF
:
2707 return gnm_cellref_hash (&expr
->cellref
.ref
);
2709 case GNM_EXPR_OP_ARRAY_CORNER
:
2710 return gnm_expr_hash (expr
->array_corner
.expr
);
2712 case GNM_EXPR_OP_ARRAY_ELEM
:
2713 return ((expr
->array_elem
.x
<< 16) ^
2714 (expr
->array_elem
.y
));
2721 /***************************************************************************/
2724 gnm_expr_sharer_new (void)
2726 GnmExprSharer
*es
= g_new (GnmExprSharer
, 1);
2728 es
->nodes_stored
= 0;
2729 es
->nodes_killed
= 0;
2730 es
->exprs
= g_hash_table_new_full
2731 ((GHashFunc
)gnm_expr_top_hash
,
2732 (GEqualFunc
)gnm_expr_top_equal
,
2733 (GDestroyNotify
)gnm_expr_top_unref
,
2740 gnm_expr_sharer_destroy (GnmExprSharer
*es
)
2742 if (!es
|| es
->ref_count
-- > 1)
2744 g_hash_table_destroy (es
->exprs
);
2748 static GnmExprSharer
*
2749 gnm_expr_sharer_ref (GnmExprSharer
*es
)
2756 gnm_expr_sharer_get_type (void)
2761 t
= g_boxed_type_register_static ("GnmExprSharer",
2762 (GBoxedCopyFunc
)gnm_expr_sharer_ref
,
2763 (GBoxedFreeFunc
)gnm_expr_sharer_destroy
);
2769 gnm_expr_sharer_share (GnmExprSharer
*es
, GnmExprTop
const *texpr
)
2771 GnmExprTop
const *shared
;
2773 g_return_val_if_fail (es
!= NULL
, texpr
);
2774 g_return_val_if_fail (texpr
!= NULL
, NULL
);
2778 /* Corners must not get shared. */
2779 if (GNM_EXPR_GET_OPER (texpr
->expr
) == GNM_EXPR_OP_ARRAY_CORNER
)
2782 shared
= g_hash_table_lookup (es
->exprs
, texpr
);
2784 gnm_expr_top_ref (shared
);
2785 if (texpr
->refcount
== 1)
2787 gnm_expr_top_unref (texpr
);
2791 gnm_expr_top_ref (texpr
);
2792 g_hash_table_insert (es
->exprs
, (gpointer
)texpr
, (gpointer
)texpr
);
2799 gnm_expr_sharer_report (GnmExprSharer
*es
)
2801 g_printerr ("Expressions in: %d\n", es
->nodes_in
);
2802 g_printerr ("Expressions stored: %d\n", es
->nodes_stored
);
2803 g_printerr ("Expressions killed: %d\n", es
->nodes_killed
);
2806 /***************************************************************************/
2809 gnm_expr_top_new (GnmExpr
const *expr
)
2816 res
= g_new (GnmExprTop
, 1);
2817 res
->magic
= GNM_EXPR_TOP_MAGIC
;
2825 gnm_expr_top_new_constant (GnmValue
*v
)
2827 return gnm_expr_top_new (gnm_expr_new_constant (v
));
2831 gnm_expr_top_ref (GnmExprTop
const *texpr
)
2833 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
2834 ((GnmExprTop
*)texpr
)->refcount
++;
2839 gnm_expr_top_unref (GnmExprTop
const *texpr
)
2841 g_return_if_fail (GNM_IS_EXPR_TOP (texpr
));
2843 ((GnmExprTop
*)texpr
)->refcount
--;
2844 if (texpr
->refcount
== 0) {
2845 gnm_expr_free (texpr
->expr
);
2846 ((GnmExprTop
*)texpr
)->magic
= 0;
2847 g_free ((GnmExprTop
*)texpr
);
2852 gnm_expr_top_get_type (void)
2857 t
= g_boxed_type_register_static ("GnmExprTop",
2858 (GBoxedCopyFunc
)gnm_expr_top_ref
,
2859 (GBoxedFreeFunc
)gnm_expr_top_unref
);
2865 gnm_expr_top_is_shared (GnmExprTop
const *texpr
)
2867 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), FALSE
);
2869 return texpr
->refcount
> 1;
2873 gnm_expr_top_new_array_corner (int cols
, int rows
, GnmExpr
const *expr
)
2875 return gnm_expr_top_new (gnm_expr_new_array_corner (cols
, rows
, expr
));
2879 gnm_expr_top_new_array_elem (int x
, int y
)
2881 return gnm_expr_top_new (gnm_expr_new_array_elem (x
, y
));
2884 static GnmExpr
const *
2885 cb_get_ranges (GnmExpr
const *expr
, GnmExprWalk
*data
)
2887 GSList
**pranges
= data
->user
;
2889 /* There's no real reason to exclude names here, except that
2890 we used to do so. */
2891 if (GNM_EXPR_GET_OPER (expr
) != GNM_EXPR_OP_NAME
) {
2892 GnmValue
*v
= gnm_expr_get_range (expr
);
2894 *pranges
= gnm_insert_unique_value (*pranges
, v
);
2901 * gnm_expr_top_get_ranges:
2904 * A collect the set of GnmRanges in @expr.
2905 * Returns: (element-type GnmRange) (transfer full): a list of the unique
2906 * references Caller is responsible for releasing the list and the content.
2909 gnm_expr_top_get_ranges (GnmExprTop
const *texpr
)
2913 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
2914 gnm_expr_walk (texpr
->expr
, cb_get_ranges
, &res
);
2919 gnm_expr_top_get_range (GnmExprTop
const *texpr
)
2921 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
2923 return gnm_expr_get_range (texpr
->expr
);
2927 gnm_expr_top_as_string (GnmExprTop
const *texpr
,
2928 GnmParsePos
const *pp
,
2929 GnmConventions
const *convs
)
2931 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
2933 return gnm_expr_as_string (texpr
->expr
, pp
, convs
);
2937 gnm_expr_top_as_gstring (GnmExprTop
const *texpr
,
2938 GnmConventionsOut
*out
)
2940 g_return_if_fail (GNM_IS_EXPR_TOP (texpr
));
2941 g_return_if_fail (out
!= NULL
);
2943 do_expr_as_string (texpr
->expr
, 0, out
);
2947 gnm_expr_top_hash (GnmExprTop
const *texpr
)
2949 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), 0);
2951 if (texpr
->hash
== 0) {
2952 ((GnmExprTop
*)texpr
)->hash
= gnm_expr_hash (texpr
->expr
);
2953 /* The following line tests the truncated value. */
2954 if (texpr
->hash
== 0)
2955 ((GnmExprTop
*)texpr
)->hash
= 1;
2961 gnm_expr_top_equal (GnmExprTop
const *te1
, GnmExprTop
const *te2
)
2965 if (te1
== NULL
|| te2
== NULL
)
2968 g_return_val_if_fail (GNM_IS_EXPR_TOP (te1
), FALSE
);
2969 g_return_val_if_fail (GNM_IS_EXPR_TOP (te2
), FALSE
);
2971 if (te1
->hash
&& te2
->hash
&& te1
->hash
!= te2
->hash
)
2974 return gnm_expr_equal (te1
->expr
, te2
->expr
);
2978 * gnm_expr_top_relocate:
2979 * @texpr: #GnmExprTop to fixup
2980 * @rinfo: #GnmExprRelocateInfo details of relocation
2981 * @ignore_rel: Do not adjust relative refs (for internal use when
2982 * relocating named expressions. Most callers will want FALSE.
2984 * GNM_EXPR_RELOCATE_INVALIDATE_SHEET:
2985 * Convert any references to sheets marked being_invalidated into #REF!
2986 * GNM_EXPR_RELOCATE_MOVE_RANGE,
2987 * Find any references to the specified area and adjust them by the
2988 * supplied deltas. Check for out of bounds conditions. Return NULL if
2989 * no change is required.
2990 * If the expression is within the range to be moved, its relative
2991 * references to cells outside the range are adjusted to reference the
2992 * same cell after the move.
2993 * GNM_EXPR_RELOCATE_COLS
2994 * GNM_EXPR_RELOCATE_ROWS
2998 gnm_expr_top_relocate (GnmExprTop
const *texpr
,
2999 GnmExprRelocateInfo
const *rinfo
,
3000 gboolean ignore_rel
)
3002 RelocInfoInternal rinfo_tmp
;
3004 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
3005 g_return_val_if_fail (NULL
!= rinfo
, NULL
);
3007 rinfo_tmp
.details
= rinfo
;
3008 rinfo_tmp
.check_rels
= !ignore_rel
;
3009 if (rinfo
->reloc_type
!= GNM_EXPR_RELOCATE_INVALIDATE_SHEET
)
3010 rinfo_tmp
.from_inside
= (rinfo
->origin_sheet
== rinfo
->pos
.sheet
) &&
3011 range_contains (&rinfo
->origin
, rinfo
->pos
.eval
.col
, rinfo
->pos
.eval
.row
);
3013 return gnm_expr_top_new (gnm_expr_relocate (texpr
->expr
, &rinfo_tmp
));
3017 * Convenience function to change an expression from one sheet to another.
3020 gnm_expr_top_relocate_sheet (GnmExprTop
const *texpr
,
3024 GnmExprRelocateInfo rinfo
;
3025 GnmExprTop
const *res
;
3027 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
3028 g_return_val_if_fail (IS_SHEET (src
), NULL
);
3029 g_return_val_if_fail (IS_SHEET (dst
), NULL
);
3031 rinfo
.reloc_type
= GNM_EXPR_RELOCATE_MOVE_RANGE
;
3032 rinfo
.origin_sheet
= (Sheet
*)src
;
3033 rinfo
.target_sheet
= (Sheet
*)dst
;
3034 rinfo
.col_offset
= rinfo
.row_offset
= 0;
3035 range_init_full_sheet (&rinfo
.origin
, src
);
3036 /* Not sure what sheet to use, but it doesn't seem to matter. */
3037 parse_pos_init_sheet (&rinfo
.pos
, rinfo
.target_sheet
);
3039 res
= gnm_expr_top_relocate (texpr
, &rinfo
, FALSE
);
3041 if (gnm_expr_top_is_array_corner (texpr
))
3042 res
= gnm_expr_top_new (gnm_expr_copy (texpr
->expr
));
3044 gnm_expr_top_ref ((res
= texpr
));
3051 gnm_expr_top_contains_subtotal (GnmExprTop
const *texpr
)
3053 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), FALSE
);
3055 return gnm_expr_contains_subtotal (texpr
->expr
);
3058 static GnmExpr
const *
3059 cb_is_volatile (GnmExpr
const *expr
, GnmExprWalk
*data
)
3061 gboolean
*res
= data
->user
;
3062 if (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_FUNCALL
&&
3063 (expr
->func
.func
->flags
& GNM_FUNC_VOLATILE
)) {
3071 gnm_expr_top_is_volatile (GnmExprTop
const *texpr
)
3073 gboolean res
= FALSE
;
3076 * An expression is volatile if it contains a call to a volatile
3077 * function, even in cases like IF(TRUE,12,RAND()) where the
3078 * volatile function won't even be reached.
3081 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), FALSE
);
3082 gnm_expr_walk (texpr
->expr
, cb_is_volatile
, &res
);
3088 gnm_expr_top_eval_array_corner (GnmExprTop
const *texpr
,
3089 GnmEvalPos
const *pos
,
3090 GnmExprEvalFlags flags
)
3092 GnmExpr
const *expr
= texpr
->expr
;
3097 pos2
.array_texpr
= texpr
;
3098 a
= gnm_expr_eval (expr
->array_corner
.expr
, &pos2
,
3099 flags
| GNM_EXPR_EVAL_PERMIT_NON_SCALAR
);
3101 value_release (expr
->array_corner
.value
);
3103 /* Store real result (cast away const)*/
3104 ((GnmExpr
*)expr
)->array_corner
.value
= a
;
3107 (VALUE_IS_CELLRANGE (a
) || VALUE_IS_ARRAY (a
))) {
3108 if (value_area_get_width (a
, pos
) <= 0 ||
3109 value_area_get_height (a
, pos
) <= 0)
3110 return value_new_error_NA (pos
);
3111 a
= (GnmValue
*)value_area_get_x_y (a
, 0, 0, pos
);
3113 return handle_empty ((a
!= NULL
) ? value_dup (a
) : NULL
, flags
);
3117 gnm_expr_top_eval_array_elem (GnmExprTop
const *texpr
,
3118 GnmEvalPos
const *pos
,
3119 GnmExprEvalFlags flags
)
3121 GnmExpr
const *expr
= texpr
->expr
;
3122 /* The upper left corner manages the recalc of the expr */
3123 GnmCell
*corner
= array_elem_get_corner (&expr
->array_elem
,
3124 pos
->sheet
, &pos
->eval
);
3128 !gnm_expr_top_is_array_corner (corner
->base
.texpr
)) {
3129 g_warning ("Funky array setup.");
3130 return handle_empty (NULL
, flags
);
3133 gnm_cell_eval (corner
);
3134 a
= gnm_expr_top_get_array_value (corner
->base
.texpr
);
3136 return handle_empty (NULL
, flags
);
3138 if ((VALUE_IS_CELLRANGE (a
) || VALUE_IS_ARRAY (a
))) {
3139 int const num_x
= value_area_get_width (a
, pos
);
3140 int const num_y
= value_area_get_height (a
, pos
);
3141 int x
= expr
->array_elem
.x
;
3142 int y
= expr
->array_elem
.y
;
3144 /* Evaluate relative to the upper left corner */
3145 GnmEvalPos tmp_ep
= *pos
;
3146 tmp_ep
.eval
.col
-= x
;
3147 tmp_ep
.eval
.row
-= y
;
3149 /* If the src array is 1 element wide or tall we wrap */
3150 if (x
>= 1 && num_x
== 1)
3152 if (y
>= 1 && num_y
== 1)
3154 if (x
>= num_x
|| y
>= num_y
)
3155 return value_new_error_NA (pos
);
3157 a
= (GnmValue
*)value_area_get_x_y (a
, x
, y
, &tmp_ep
);
3160 return handle_empty ((a
!= NULL
) ? value_dup (a
) : NULL
, flags
);
3164 gnm_expr_top_eval (GnmExprTop
const *texpr
,
3165 GnmEvalPos
const *pos
,
3166 GnmExprEvalFlags flags
)
3170 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
3172 gnm_app_recalc_start ();
3174 if (gnm_expr_top_is_array_corner (texpr
))
3175 res
= gnm_expr_top_eval_array_corner (texpr
, pos
, flags
);
3176 else if (gnm_expr_top_is_array_elem (texpr
, NULL
, NULL
))
3177 res
= gnm_expr_top_eval_array_elem (texpr
, pos
, flags
);
3178 else if ((flags
& GNM_EXPR_EVAL_ARRAY_CONTEXT
) && !eval_pos_is_array_context (pos
)) {
3179 // Array context out of the blue. Fake it.
3181 GnmExprTop
const *fake
= gnm_expr_top_new_array_corner (1, 1, NULL
);
3182 ((GnmExpr
*)(fake
->expr
))->array_corner
.expr
= texpr
->expr
; // Patch in our expr
3184 pos2
.array_texpr
= fake
;
3185 res
= gnm_expr_eval (texpr
->expr
, &pos2
, flags
);
3186 ((GnmExpr
*)(fake
->expr
))->array_corner
.expr
= NULL
;
3187 gnm_expr_top_unref (fake
);
3189 res
= gnm_expr_eval (texpr
->expr
, pos
, flags
);
3190 gnm_app_recalc_finish ();
3196 gnm_insert_unique (GSList
*list
, gpointer data
)
3198 if (g_slist_find (list
, data
) == NULL
)
3199 return g_slist_prepend (list
, data
);
3203 static GnmExpr
const *
3204 cb_referenced_sheets (GnmExpr
const *expr
, GnmExprWalk
*data
)
3206 GSList
**psheets
= data
->user
;
3208 switch (GNM_EXPR_GET_OPER (expr
)) {
3209 case GNM_EXPR_OP_CELLREF
:
3210 *psheets
= gnm_insert_unique (*psheets
, expr
->cellref
.ref
.sheet
);
3213 case GNM_EXPR_OP_CONSTANT
: {
3214 GnmValue
const *v
= expr
->constant
.value
;
3215 if (!VALUE_IS_CELLRANGE (v
))
3217 *psheets
= gnm_insert_unique (*psheets
, v
->v_range
.cell
.a
.sheet
);
3218 /* A NULL b sheet means a's sheet. Do not insert that. */
3219 if (v
->v_range
.cell
.b
.sheet
)
3220 *psheets
= gnm_insert_unique (*psheets
, v
->v_range
.cell
.b
.sheet
);
3232 * gnm_expr_top_referenced_sheets:
3235 * Generates a list of the sheets referenced by the supplied expression.
3236 * Caller must free the list. Note, that NULL may occur in the result
3237 * if the expression has a range or cellref without a sheet.
3238 * Returns: (element-type Sheet) (transfer container): the created list.
3241 gnm_expr_top_referenced_sheets (GnmExprTop
const *texpr
)
3245 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
3246 gnm_expr_walk (texpr
->expr
, cb_referenced_sheets
, &res
);
3251 gnm_expr_top_is_err (GnmExprTop
const *texpr
, GnmStdError err
)
3253 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), FALSE
);
3254 return gnm_expr_is_err (texpr
->expr
, err
);
3258 * gnm_expr_top_get_constant:
3261 * If this expression consists of just a constant, return it.
3264 gnm_expr_top_get_constant (GnmExprTop
const *texpr
)
3266 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
3268 return gnm_expr_get_constant (texpr
->expr
);
3272 gnm_expr_top_get_cellref (GnmExprTop
const *texpr
)
3274 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
3275 return gnm_expr_get_cellref (texpr
->expr
);
3278 static GnmExpr
const *
3279 cb_first_funcall (GnmExpr
const *expr
, GnmExprWalk
*data
)
3281 GnmExprConstPtr
*user
= data
->user
;
3282 if (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_FUNCALL
) {
3290 * gnm_expr_top_first_funcall:
3295 gnm_expr_top_first_funcall (GnmExprTop
const *texpr
)
3297 GnmExpr
const *res
= NULL
;
3299 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
3300 gnm_expr_walk (texpr
->expr
, cb_first_funcall
, &res
);
3304 struct cb_get_boundingbox
{
3309 static GnmExpr
const *
3310 cb_get_boundingbox (GnmExpr
const *expr
, GnmExprWalk
*data
)
3312 struct cb_get_boundingbox
*args
= data
->user
;
3314 switch (GNM_EXPR_GET_OPER (expr
)) {
3315 case GNM_EXPR_OP_CELLREF
:
3316 cellref_boundingbox (&expr
->cellref
.ref
, args
->sheet
, args
->bound
);
3319 case GNM_EXPR_OP_CONSTANT
: {
3320 GnmValue
const *v
= expr
->constant
.value
;
3322 if (VALUE_IS_CELLRANGE (v
)) {
3323 cellref_boundingbox (&v
->v_range
.cell
.a
, args
->sheet
, args
->bound
);
3324 cellref_boundingbox (&v
->v_range
.cell
.b
, args
->sheet
, args
->bound
);
3337 * gnm_expr_top_get_boundingbox:
3339 * Returns the range of cells in which the expression can be used without going
3343 gnm_expr_top_get_boundingbox (GnmExprTop
const *texpr
, Sheet
const *sheet
,
3346 struct cb_get_boundingbox args
;
3348 g_return_if_fail (GNM_IS_EXPR_TOP (texpr
));
3350 range_init_full_sheet (bound
, sheet
);
3354 gnm_expr_walk (texpr
->expr
, cb_get_boundingbox
, &args
);
3358 gnm_expr_top_is_rangeref (GnmExprTop
const *texpr
)
3360 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), FALSE
);
3362 return gnm_expr_is_rangeref (texpr
->expr
);
3366 gnm_expr_top_is_array_corner (GnmExprTop
const *texpr
)
3368 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), FALSE
);
3369 return GNM_EXPR_GET_OPER (texpr
->expr
) == GNM_EXPR_OP_ARRAY_CORNER
;
3373 gnm_expr_top_get_array_size (GnmExprTop
const *texpr
, int *cols
, int *rows
)
3375 g_return_if_fail (GNM_IS_EXPR_TOP (texpr
));
3376 g_return_if_fail (GNM_EXPR_GET_OPER (texpr
->expr
) == GNM_EXPR_OP_ARRAY_CORNER
);
3379 *cols
= texpr
->expr
->array_corner
.cols
;
3381 *rows
= texpr
->expr
->array_corner
.rows
;
3385 gnm_expr_top_get_array_value (GnmExprTop
const *texpr
)
3387 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
3388 g_return_val_if_fail (GNM_EXPR_GET_OPER (texpr
->expr
) == GNM_EXPR_OP_ARRAY_CORNER
, NULL
);
3389 return texpr
->expr
->array_corner
.value
;
3393 gnm_expr_top_get_array_expr (GnmExprTop
const *texpr
)
3395 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
3396 g_return_val_if_fail (GNM_EXPR_GET_OPER (texpr
->expr
) == GNM_EXPR_OP_ARRAY_CORNER
, NULL
);
3397 return texpr
->expr
->array_corner
.expr
;
3401 gnm_expr_top_is_array_elem (GnmExprTop
const *texpr
, int *x
, int *y
)
3403 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), FALSE
);
3405 if (GNM_EXPR_GET_OPER (texpr
->expr
) != GNM_EXPR_OP_ARRAY_ELEM
)
3408 if (x
) *x
= texpr
->expr
->array_elem
.x
;
3409 if (y
) *y
= texpr
->expr
->array_elem
.y
;
3414 gnm_expr_top_is_array (GnmExprTop
const *texpr
)
3416 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), FALSE
);
3417 return gnm_expr_is_array (texpr
->expr
);
3421 gnm_expr_top_transpose (GnmExprTop
const *texpr
)
3423 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
3424 switch (GNM_EXPR_GET_OPER (texpr
->expr
)) {
3425 case GNM_EXPR_OP_ARRAY_CORNER
:
3426 /* Transpose size */
3427 return gnm_expr_top_new_array_corner
3428 (texpr
->expr
->array_corner
.rows
,
3429 texpr
->expr
->array_corner
.cols
,
3430 gnm_expr_copy (texpr
->expr
));
3431 case GNM_EXPR_OP_ARRAY_ELEM
:
3432 /* Transpose coordinates */
3433 return gnm_expr_top_new_array_elem
3434 (texpr
->expr
->array_elem
.y
,
3435 texpr
->expr
->array_elem
.x
);
3441 /****************************************************************************/
3445 guint32 oper_and_refcount
;
3446 GnmExprConstant constant
;
3447 GnmExprFunction func
;
3449 GnmExprBinary binary
;
3450 GnmExprArrayElem array_elem
;
3454 guint32 oper_and_refcount
;
3456 GnmExprCellRef cellref
;
3457 GnmExprArrayCorner array_corner
;
3462 * _gnm_expr_init: (skip)
3465 _gnm_expr_init (void)
3471 /* 12 is an excellent size for a pool. */
3472 g_print ("sizeof(GnmExprSmall) = %d\n", (int)sizeof (GnmExprSmall
));
3473 g_print ("sizeof(GnmExprBig) = %d\n", (int)sizeof (GnmExprBig
));
3475 g_print ("sizeof(e.func) = %d\n", (int)sizeof (e
.func
));
3476 g_print ("sizeof(e.unary) = %d\n", (int)sizeof (e
.unary
));
3477 g_print ("sizeof(e.binary) = %d\n", (int)sizeof (e
.binary
));
3478 g_print ("sizeof(e.name) = %d\n", (int)sizeof (e
.name
));
3479 g_print ("sizeof(e.cellref) = %d\n", (int)sizeof (e
.cellref
));
3480 g_print ("sizeof(e.array_corner) = %d\n", (int)sizeof (e
.array_corner
));
3481 g_print ("sizeof(e.array_elem) = %d\n", (int)sizeof (e
.array_elem
));
3482 g_print ("sizeof(e.set) = %d\n", (int)sizeof (e
.set
));
3485 expression_pool_small
=
3486 go_mem_chunk_new ("expression pool for small nodes",
3487 sizeof (GnmExprSmall
),
3489 expression_pool_big
=
3490 go_mem_chunk_new ("expression pool for big nodes",
3491 sizeof (GnmExprBig
),
3498 cb_expression_pool_leak (gpointer data
, G_GNUC_UNUSED gpointer user
)
3500 GnmExpr
const *expr
= data
;
3508 s
= gnm_expr_as_string (expr
, &pp
, NULL
);
3509 g_printerr ("Leaking expression at %p: %s.\n", (void *)expr
, s
);
3515 * _gnm_expr_shutdown: (skip)
3518 _gnm_expr_shutdown (void)
3521 go_mem_chunk_foreach_leak (expression_pool_small
, cb_expression_pool_leak
, NULL
);
3522 go_mem_chunk_destroy (expression_pool_small
, FALSE
);
3523 expression_pool_small
= NULL
;
3525 go_mem_chunk_foreach_leak (expression_pool_big
, cb_expression_pool_leak
, NULL
);
3526 go_mem_chunk_destroy (expression_pool_big
, FALSE
);
3527 expression_pool_big
= NULL
;
3531 /****************************************************************************/