2 * expr.c : Expression evaluation in Gnumeric
4 * Copyright (C) 2001-2006 Jody Goldberg (jody@gnome.org)
5 * Copyright (C) 1998-2000 Miguel de Icaza (miguel@gnu.org)
6 * Copyright (C) 2000-2018 Morten Welinder (terra@gnome.org)
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) version 3.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
23 #include <gnumeric-config.h>
24 #include <glib/gi18n-lib.h>
28 #include <expr-impl.h>
29 #include <expr-name.h>
30 #include <dependent.h>
31 #include <application.h>
36 #include <parse-util.h>
38 #include <number-match.h>
41 #include <parse-util.h>
44 #include <goffice/goffice.h>
50 * Using pools here probably does not save anything, but it's a darn
51 * good debugging tool.
53 #ifndef USE_EXPR_POOLS
54 #define USE_EXPR_POOLS 1
58 /* Memory pools for expressions. */
59 static GOMemChunk
*expression_pool_small
, *expression_pool_big
;
60 #define CHUNK_ALLOC(T,p) ((T*)go_mem_chunk_alloc (p))
61 #define CHUNK_FREE(p,v) go_mem_chunk_free ((p), (v))
63 #define CHUNK_ALLOC(T,c) g_new (T,1)
64 #define CHUNK_FREE(p,v) g_free ((v))
67 /***************************************************************************/
70 * gnm_expr_new_constant:
71 * @v: (transfer full): #GnmValue
73 * Returns: (transfer full): constant expression.
76 gnm_expr_new_constant (GnmValue
*v
)
80 g_return_val_if_fail (v
!= NULL
, NULL
);
82 ans
= CHUNK_ALLOC (GnmExprConstant
, expression_pool_small
);
85 gnm_expr_constant_init (ans
, v
);
87 return (GnmExpr
*)ans
;
90 /***************************************************************************/
93 * gnm_expr_new_funcallv: (skip)
95 * @argc: argument count
96 * @argv: (array length=argc): transfers everything
98 * Returns: (transfer full): function call expression.
100 static GnmExpr
const *
101 gnm_expr_new_funcallv (GnmFunc
*func
, int argc
, GnmExprConstPtr
*argv
)
103 GnmExprFunction
*ans
;
104 g_return_val_if_fail (func
, NULL
);
106 ans
= CHUNK_ALLOC (GnmExprFunction
, expression_pool_small
);
108 ans
->oper
= GNM_EXPR_OP_FUNCALL
;
109 gnm_func_inc_usage (func
);
114 return (GnmExpr
*)ans
;
118 * gnm_expr_new_funcall:
120 * @args: (transfer full): argument list
122 * Returns: (transfer full): function call expression.
125 gnm_expr_new_funcall (GnmFunc
*func
, GnmExprList
*args
)
127 int argc
= gnm_expr_list_length (args
);
128 GnmExprConstPtr
*argv
= NULL
;
131 GnmExprList
*args0
= args
;
134 argv
= g_new (GnmExprConstPtr
, argc
);
135 for (; args
; args
= args
->next
)
136 argv
[i
++] = args
->data
;
137 gnm_expr_list_free (args0
);
140 return gnm_expr_new_funcallv (func
, argc
, argv
);
144 * gnm_expr_new_funcall1:
146 * @arg0: (transfer full): argument
148 * Returns: (transfer full): function call expression.
151 gnm_expr_new_funcall1 (GnmFunc
*func
,
154 GnmExprConstPtr
*argv
= g_new (GnmExprConstPtr
, 1);
156 return gnm_expr_new_funcallv (func
, 1, argv
);
160 * gnm_expr_new_funcall2:
162 * @arg0: (transfer full): argument
163 * @arg1: (transfer full): argument
165 * Returns: (transfer full): function call expression.
168 gnm_expr_new_funcall2 (GnmFunc
*func
,
172 GnmExprConstPtr
*argv
= g_new (GnmExprConstPtr
, 2);
175 return gnm_expr_new_funcallv (func
, 2, argv
);
179 * gnm_expr_new_funcall3:
181 * @arg0: (transfer full): argument
182 * @arg1: (transfer full): argument
183 * @arg2: (transfer full): argument
185 * Returns: (transfer full): function call expression.
188 gnm_expr_new_funcall3 (GnmFunc
*func
,
193 GnmExprConstPtr
*argv
= g_new (GnmExprConstPtr
, 3);
197 return gnm_expr_new_funcallv (func
, 3, argv
);
201 * gnm_expr_new_funcall4:
203 * @arg0: (transfer full): argument
204 * @arg1: (transfer full): argument
205 * @arg2: (transfer full): argument
206 * @arg3: (transfer full): argument
208 * Returns: (transfer full): function call expression.
211 gnm_expr_new_funcall4 (GnmFunc
*func
,
217 GnmExprConstPtr
*argv
= g_new (GnmExprConstPtr
, 4);
222 return gnm_expr_new_funcallv (func
, 4, argv
);
226 * gnm_expr_new_funcall5:
228 * @arg0: (transfer full): argument
229 * @arg1: (transfer full): argument
230 * @arg2: (transfer full): argument
231 * @arg3: (transfer full): argument
232 * @arg4: (transfer full): argument
234 * Returns: (transfer full): function call expression.
237 gnm_expr_new_funcall5 (GnmFunc
*func
,
244 GnmExprConstPtr
*argv
= g_new (GnmExprConstPtr
, 5);
250 return gnm_expr_new_funcallv (func
, 5, argv
);
254 /***************************************************************************/
257 * gnm_expr_new_unary:
258 * @op: Unary operator
259 * @e: (transfer full): #GnmExpr
261 * Returns: (transfer full): Unary expresssion
264 gnm_expr_new_unary (GnmExprOp op
, GnmExpr
const *e
)
268 ans
= CHUNK_ALLOC (GnmExprUnary
, expression_pool_small
);
275 return (GnmExpr
*)ans
;
278 /***************************************************************************/
281 * gnm_expr_new_binary:
282 * @l: (transfer full): left operand.
283 * @op: Unary operator
284 * @r: (transfer full): right operand.
286 * Returns: (transfer full): Binary expresssion
289 gnm_expr_new_binary (GnmExpr
const *l
, GnmExprOp op
, GnmExpr
const *r
)
293 ans
= CHUNK_ALLOC (GnmExprBinary
, expression_pool_small
);
301 return (GnmExpr
*)ans
;
304 /***************************************************************************/
307 gnm_expr_new_name (GnmNamedExpr
*name
,
308 Sheet
*optional_scope
, Workbook
*optional_wb_scope
)
312 ans
= CHUNK_ALLOC (GnmExprName
, expression_pool_big
);
316 ans
->oper
= GNM_EXPR_OP_NAME
;
318 expr_name_ref (name
);
320 ans
->optional_scope
= optional_scope
;
321 ans
->optional_wb_scope
= optional_wb_scope
;
323 return (GnmExpr
*)ans
;
326 /***************************************************************************/
329 * gnm_expr_new_cellref:
330 * @cr: (transfer none): cell reference
332 * Returns: (transfer full): expression referencing @cr.
335 gnm_expr_new_cellref (GnmCellRef
const *cr
)
339 ans
= CHUNK_ALLOC (GnmExprCellRef
, expression_pool_big
);
343 ans
->oper
= GNM_EXPR_OP_CELLREF
;
346 return (GnmExpr
*)ans
;
349 /***************************************************************************/
355 * Returns: %TRUE if @expr is an array expression, either a corner or a
356 * non-corner element.
359 gnm_expr_is_array (GnmExpr
const *expr
)
362 (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_ARRAY_ELEM
||
363 GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_ARRAY_CORNER
);
367 * gnm_expr_new_array_corner:
368 * @cols: Number of columns
369 * @rows: Number of rows
370 * @expr: (transfer full) (nullable): #GnmExpr
372 * Returns: (transfer full): An array corner expression
374 static GnmExpr
const *
375 gnm_expr_new_array_corner(int cols
, int rows
, GnmExpr
const *expr
)
377 GnmExprArrayCorner
*ans
;
379 g_return_val_if_fail (!gnm_expr_is_array (expr
), NULL
);
381 ans
= CHUNK_ALLOC (GnmExprArrayCorner
, expression_pool_big
);
382 ans
->oper
= GNM_EXPR_OP_ARRAY_CORNER
;
387 return (GnmExpr
*)ans
;
391 * gnm_expr_new_array_elem:
392 * @x: Column number relative to corner
393 * @y: Row number relative to corner
395 * Returns: (transfer full): An array non-corner expression
397 static GnmExpr
const *
398 gnm_expr_new_array_elem (int x
, int y
)
400 GnmExprArrayElem
*ans
;
402 ans
= CHUNK_ALLOC (GnmExprArrayElem
, expression_pool_small
);
403 ans
->oper
= GNM_EXPR_OP_ARRAY_ELEM
;
406 return (GnmExpr
*)ans
;
409 /***************************************************************************/
411 static GnmExpr
const *
412 gnm_expr_new_setv (int argc
, GnmExprConstPtr
*argv
)
414 GnmExprSet
*ans
= CHUNK_ALLOC (GnmExprSet
, expression_pool_small
);
416 ans
->oper
= GNM_EXPR_OP_SET
;
420 return (GnmExpr
*)ans
;
425 * @args: (transfer full): element list
427 * Returns: (transfer full): set expression.
430 gnm_expr_new_set (GnmExprList
*set
)
433 GnmExprConstPtr
*argv
;
434 GnmExprList
*set0
= set
;
436 argc
= gnm_expr_list_length (set
);
437 argv
= argc
? g_new (GnmExprConstPtr
, argc
) : NULL
;
438 for (i
= 0; set
; i
++, set
= set
->next
)
440 gnm_expr_list_free (set0
);
442 return gnm_expr_new_setv (argc
, argv
);
445 /***************************************************************************/
448 * gnm_expr_new_range_ctor:
449 * @l: (transfer full): start range
450 * @r: (transfer full): end range
452 * This function builds a range constructor or something simpler,
453 * but equivalent, if the arguments allow it.
455 * Returns: (transfer full): And expression referencing @l to @r.
458 gnm_expr_new_range_ctor (GnmExpr
const *l
, GnmExpr
const *r
)
462 g_return_val_if_fail (l
!= NULL
, NULL
);
463 g_return_val_if_fail (r
!= NULL
, NULL
);
465 if (GNM_EXPR_GET_OPER (l
) != GNM_EXPR_OP_CELLREF
)
467 if (GNM_EXPR_GET_OPER (r
) != GNM_EXPR_OP_CELLREF
)
470 v
= value_new_cellrange_unsafe (&l
->cellref
.ref
, &r
->cellref
.ref
);
473 return gnm_expr_new_constant (v
);
476 return gnm_expr_new_binary (l
, GNM_EXPR_OP_RANGE_CTOR
, r
);
479 /***************************************************************************/
483 * @expr: (transfer none): #GnmExpr
485 * Returns: (transfer full): A deep copy of @expr.
488 gnm_expr_copy (GnmExpr
const *expr
)
490 g_return_val_if_fail (expr
!= NULL
, NULL
);
492 switch (GNM_EXPR_GET_OPER (expr
)) {
493 case GNM_EXPR_OP_RANGE_CTOR
:
494 case GNM_EXPR_OP_INTERSECT
:
495 case GNM_EXPR_OP_ANY_BINARY
:
496 return gnm_expr_new_binary
497 (gnm_expr_copy (expr
->binary
.value_a
),
498 GNM_EXPR_GET_OPER (expr
),
499 gnm_expr_copy (expr
->binary
.value_b
));
501 case GNM_EXPR_OP_ANY_UNARY
:
502 return gnm_expr_new_unary
503 (GNM_EXPR_GET_OPER (expr
),
504 gnm_expr_copy (expr
->unary
.value
));
506 case GNM_EXPR_OP_FUNCALL
: {
507 GnmExprConstPtr
*argv
=
508 g_new (GnmExprConstPtr
, expr
->func
.argc
);
511 for (i
= 0; i
< expr
->func
.argc
; i
++)
512 argv
[i
] = gnm_expr_copy (expr
->func
.argv
[i
]);
514 return gnm_expr_new_funcallv
520 case GNM_EXPR_OP_NAME
:
521 return gnm_expr_new_name
523 expr
->name
.optional_scope
,
524 expr
->name
.optional_wb_scope
);
526 case GNM_EXPR_OP_CONSTANT
:
527 return gnm_expr_new_constant
528 (value_dup (expr
->constant
.value
));
530 case GNM_EXPR_OP_CELLREF
:
531 return gnm_expr_new_cellref (&expr
->cellref
.ref
);
533 case GNM_EXPR_OP_ARRAY_CORNER
:
534 return gnm_expr_new_array_corner
535 (expr
->array_corner
.cols
, expr
->array_corner
.rows
,
536 gnm_expr_copy (expr
->array_corner
.expr
));
538 case GNM_EXPR_OP_ARRAY_ELEM
:
539 return gnm_expr_new_array_elem
543 case GNM_EXPR_OP_SET
: {
544 GnmExprConstPtr
*argv
=
545 g_new (GnmExprConstPtr
, expr
->set
.argc
);
548 for (i
= 0; i
< expr
->set
.argc
; i
++)
549 argv
[i
] = gnm_expr_copy (expr
->set
.argv
[i
]);
551 return gnm_expr_new_setv
556 #ifndef DEBUG_SWITCH_ENUM
558 g_assert_not_reached ();
566 * @expr: (transfer full): #GnmExpr
568 * Deletes @expr with all its subexpressions.
571 gnm_expr_free (GnmExpr
const *expr
)
573 g_return_if_fail (expr
!= NULL
);
575 switch (GNM_EXPR_GET_OPER (expr
)) {
576 case GNM_EXPR_OP_RANGE_CTOR
:
577 case GNM_EXPR_OP_INTERSECT
:
578 case GNM_EXPR_OP_ANY_BINARY
:
579 gnm_expr_free (expr
->binary
.value_a
);
580 gnm_expr_free (expr
->binary
.value_b
);
581 CHUNK_FREE (expression_pool_small
, (gpointer
)expr
);
584 case GNM_EXPR_OP_FUNCALL
: {
587 for (i
= 0; i
< expr
->func
.argc
; i
++)
588 gnm_expr_free (expr
->func
.argv
[i
]);
589 g_free (expr
->func
.argv
);
590 gnm_func_dec_usage (expr
->func
.func
);
591 CHUNK_FREE (expression_pool_small
, (gpointer
)expr
);
595 case GNM_EXPR_OP_NAME
:
596 expr_name_unref (expr
->name
.name
);
597 CHUNK_FREE (expression_pool_big
, (gpointer
)expr
);
600 case GNM_EXPR_OP_CONSTANT
:
601 value_release ((GnmValue
*)expr
->constant
.value
);
602 CHUNK_FREE (expression_pool_small
, (gpointer
)expr
);
605 case GNM_EXPR_OP_CELLREF
:
606 CHUNK_FREE (expression_pool_big
, (gpointer
)expr
);
609 case GNM_EXPR_OP_ANY_UNARY
:
610 gnm_expr_free (expr
->unary
.value
);
611 CHUNK_FREE (expression_pool_small
, (gpointer
)expr
);
614 case GNM_EXPR_OP_ARRAY_CORNER
:
615 value_release (expr
->array_corner
.value
);
616 // A proper corner will not have NULL here, but we explicitly allow it
617 // during construction, so allow it here too.
618 if (expr
->array_corner
.expr
)
619 gnm_expr_free (expr
->array_corner
.expr
);
620 CHUNK_FREE (expression_pool_big
, (gpointer
)expr
);
623 case GNM_EXPR_OP_ARRAY_ELEM
:
624 CHUNK_FREE (expression_pool_small
, (gpointer
)expr
);
627 case GNM_EXPR_OP_SET
: {
630 for (i
= 0; i
< expr
->set
.argc
; i
++)
631 gnm_expr_free (expr
->set
.argv
[i
]);
632 g_free (expr
->set
.argv
);
633 CHUNK_FREE (expression_pool_small
, (gpointer
)expr
);
637 #ifndef DEBUG_SWITCH_ENUM
639 g_assert_not_reached ();
646 gnm_expr_get_type (void)
651 t
= g_boxed_type_register_static ("GnmExpr",
652 (GBoxedCopyFunc
)gnm_expr_copy
,
653 (GBoxedFreeFunc
)gnm_expr_free
);
659 gnm_expr_array_corner_get_type (void)
664 t
= g_boxed_type_register_static ("GnmExprArrayCorner",
665 (GBoxedCopyFunc
)gnm_expr_copy
,
666 (GBoxedFreeFunc
)gnm_expr_free
);
676 * Returns: %TRUE, if the supplied expressions are exactly the
677 * same and %FALSE otherwise. No eval position is used to see if they
678 * are effectively the same. Named expressions must refer the same name,
679 * having equivalent names is insufficeient.
682 gnm_expr_equal (GnmExpr
const *a
, GnmExpr
const *b
)
687 g_return_val_if_fail (a
!= NULL
, FALSE
);
688 g_return_val_if_fail (b
!= NULL
, FALSE
);
690 if (GNM_EXPR_GET_OPER (a
) != GNM_EXPR_GET_OPER (b
))
693 switch (GNM_EXPR_GET_OPER (a
)) {
694 case GNM_EXPR_OP_RANGE_CTOR
:
695 case GNM_EXPR_OP_INTERSECT
:
696 case GNM_EXPR_OP_ANY_BINARY
:
697 return gnm_expr_equal (a
->binary
.value_a
, b
->binary
.value_a
) &&
698 gnm_expr_equal (a
->binary
.value_b
, b
->binary
.value_b
);
700 case GNM_EXPR_OP_ANY_UNARY
:
701 return gnm_expr_equal (a
->unary
.value
, b
->unary
.value
);
703 case GNM_EXPR_OP_FUNCALL
: {
706 if (a
->func
.func
!= b
->func
.func
||
707 a
->func
.argc
!= b
->func
.argc
)
710 for (i
= 0; i
< a
->func
.argc
; i
++)
711 if (!gnm_expr_equal (a
->func
.argv
[i
], b
->func
.argv
[i
]))
716 case GNM_EXPR_OP_NAME
:
717 return a
->name
.name
== b
->name
.name
&&
718 a
->name
.optional_scope
== b
->name
.optional_scope
&&
719 a
->name
.optional_wb_scope
== b
->name
.optional_wb_scope
;
721 case GNM_EXPR_OP_CELLREF
:
722 return gnm_cellref_equal (&a
->cellref
.ref
, &b
->cellref
.ref
);
724 case GNM_EXPR_OP_CONSTANT
:
725 return value_equal (a
->constant
.value
, b
->constant
.value
);
727 case GNM_EXPR_OP_ARRAY_CORNER
: {
728 GnmExprArrayCorner
const *aa
= &a
->array_corner
;
729 GnmExprArrayCorner
const *ab
= &b
->array_corner
;
731 return aa
->cols
== ab
->cols
&&
732 aa
->rows
== ab
->rows
&&
733 gnm_expr_equal (aa
->expr
, ab
->expr
);
735 case GNM_EXPR_OP_ARRAY_ELEM
: {
736 GnmExprArrayElem
const *aa
= &a
->array_elem
;
737 GnmExprArrayElem
const *ab
= &b
->array_elem
;
738 return aa
->x
== ab
->x
&& aa
->y
== ab
->y
;
741 case GNM_EXPR_OP_SET
: {
744 if (a
->set
.argc
!= b
->set
.argc
)
747 for (i
= 0; i
< a
->set
.argc
; i
++)
748 if (!gnm_expr_equal (a
->set
.argv
[i
], b
->set
.argv
[i
]))
758 array_elem_get_corner (GnmExprArrayElem
const *elem
,
759 Sheet
const *sheet
, GnmCellPos
const *pos
)
761 GnmCell
*corner
= sheet_cell_get (sheet
,
762 pos
->col
- elem
->x
, pos
->row
- elem
->y
);
764 /* Sanity check incase the corner gets removed for some reason */
765 g_return_val_if_fail (corner
!= NULL
, NULL
);
766 g_return_val_if_fail (gnm_cell_has_expr (corner
), NULL
);
767 g_return_val_if_fail (corner
->base
.texpr
!= (void *)0xdeadbeef, NULL
);
768 g_return_val_if_fail (GNM_IS_EXPR_TOP (corner
->base
.texpr
), NULL
);
774 gnm_expr_extract_ref (GnmRangeRef
*res
, GnmExpr
const *expr
,
775 GnmEvalPos
const *pos
, GnmExprEvalFlags flags
)
777 switch (GNM_EXPR_GET_OPER (expr
)) {
778 case GNM_EXPR_OP_FUNCALL
: {
779 gboolean failed
= TRUE
;
784 ei
.func_call
= &expr
->func
;
786 v
= function_call_with_exprs (&ei
);
789 if (VALUE_IS_CELLRANGE (v
)) {
790 *res
= v
->v_range
.cell
;
798 case GNM_EXPR_OP_CELLREF
:
799 res
->a
= expr
->cellref
.ref
;
800 res
->b
= expr
->cellref
.ref
;
803 case GNM_EXPR_OP_CONSTANT
: {
804 GnmValue
const *v
= expr
->constant
.value
;
805 if (VALUE_IS_CELLRANGE (v
)) {
806 *res
= v
->v_range
.cell
;
812 case GNM_EXPR_OP_NAME
:
813 if (!expr_name_is_active (expr
->name
.name
))
815 return gnm_expr_extract_ref (res
, expr
->name
.name
->texpr
->expr
,
823 static inline GnmValue
*
824 handle_empty (GnmValue
*res
, GnmExprEvalFlags flags
)
827 return (flags
& GNM_EXPR_EVAL_PERMIT_EMPTY
)
828 ? NULL
: value_new_int (0);
830 if (VALUE_IS_EMPTY (res
)) {
832 return (flags
& GNM_EXPR_EVAL_PERMIT_EMPTY
)
833 ? NULL
: value_new_int (0);
839 * value_intersection:
840 * @v: a VALUE_CELLRANGE or VALUE_ARRAY
843 * Handle the implicit union of a single row or column with the eval position.
845 * NOTE : We do not need to know if this is expression is being evaluated as an
846 * array or not because we can differentiate based on the required type for the
849 * Always release the value passed in.
852 * If the intersection succeeded return a duplicate of the value
853 * at the intersection point. This value needs to be freed.
854 * NULL if there is no intersection
855 * Returns the upper left corner of an array.
858 value_intersection (GnmValue
*v
, GnmEvalPos
const *pos
)
860 GnmValue
*res
= NULL
;
862 Sheet
*start_sheet
, *end_sheet
;
863 gboolean found
= FALSE
;
865 if (VALUE_IS_ARRAY (v
)) {
866 res
= (v
->v_array
.x
== 0 || v
->v_array
.y
== 0)
867 ? value_new_error_VALUE (NULL
)
868 : value_dup (v
->v_array
.vals
[0][0]);
873 /* inverted ranges */
874 gnm_rangeref_normalize (&v
->v_range
.cell
, pos
, &start_sheet
, &end_sheet
, &r
);
877 if (start_sheet
== end_sheet
|| end_sheet
== NULL
) {
878 int col
= pos
->eval
.col
;
879 int row
= pos
->eval
.row
;
881 if (pos
->dep
&& !dependent_is_cell (pos
->dep
)) {
882 /* See bug #142412. */
886 } else if (r
.start
.row
== r
.end
.row
) {
887 if (r
.start
.col
<= col
&& col
<= r
.end
.col
) {
890 } else if (r
.start
.col
== r
.end
.col
) {
895 } else if (r
.start
.col
== r
.end
.col
) {
896 if (r
.start
.row
<= row
&& row
<= r
.end
.row
) {
902 GnmCell
*cell
= sheet_cell_get (
903 eval_sheet (start_sheet
, pos
->sheet
),
906 return value_new_empty ();
907 gnm_cell_eval (cell
);
908 return value_dup (cell
->value
);
912 return value_new_error_VALUE (pos
);
916 bin_arith (GnmExpr
const *expr
, GnmEvalPos
const *ep
,
917 GnmValue
const *a
, GnmValue
const *b
)
919 gnm_float
const va
= value_get_as_float (a
);
920 gnm_float
const vb
= value_get_as_float (b
);
923 switch (GNM_EXPR_GET_OPER (expr
)) {
924 case GNM_EXPR_OP_ADD
:
928 case GNM_EXPR_OP_SUB
:
932 case GNM_EXPR_OP_MULT
:
936 case GNM_EXPR_OP_DIV
:
938 return value_new_error_DIV0 (ep
);
942 case GNM_EXPR_OP_EXP
:
943 if ((va
== 0 && vb
<= 0) || (va
< 0 && vb
!= (int)vb
))
944 return value_new_error_NUM (ep
);
946 res
= gnm_pow (va
, vb
);
950 g_assert_not_reached ();
953 if (gnm_finite (res
))
954 return value_new_float (res
);
956 return value_new_error_NUM (ep
);
960 bin_cmp (GnmExprOp op
, GnmValDiff comp
, GnmEvalPos
const *ep
)
962 if (comp
== TYPE_MISMATCH
) {
963 /* TODO TODO TODO : Make error more informative
964 * regarding what is comparing to what
966 /* For equality comparisons even errors are ok */
967 if (op
== GNM_EXPR_OP_EQUAL
)
968 return value_new_bool (FALSE
);
969 if (op
== GNM_EXPR_OP_NOT_EQUAL
)
970 return value_new_bool (TRUE
);
972 return value_new_error_VALUE (ep
);
976 case GNM_EXPR_OP_EQUAL
: return value_new_bool (comp
== IS_EQUAL
);
977 case GNM_EXPR_OP_GT
: return value_new_bool (comp
== IS_GREATER
);
978 case GNM_EXPR_OP_LT
: return value_new_bool (comp
== IS_LESS
);
979 case GNM_EXPR_OP_NOT_EQUAL
: return value_new_bool (comp
!= IS_EQUAL
);
980 case GNM_EXPR_OP_LTE
: return value_new_bool (comp
!= IS_GREATER
);
981 case GNM_EXPR_OP_GTE
: return value_new_bool (comp
!= IS_LESS
);
983 #ifndef DEBUG_SWITCH_ENUM
985 g_assert_not_reached ();
988 return value_new_error (ep
, _("Internal type error"));
992 cb_bin_cmp (GnmEvalPos
const *ep
, GnmValue
const *a
, GnmValue
const *b
,
995 if (a
!= NULL
&& VALUE_IS_ERROR (a
))
996 return value_dup (a
);
997 if (b
!= NULL
&& VALUE_IS_ERROR (b
))
998 return value_dup (b
);
999 return bin_cmp (GNM_EXPR_GET_OPER (expr
), value_compare (a
, b
, FALSE
), ep
);
1003 cb_bin_arith (GnmEvalPos
const *ep
, GnmValue
const *a
, GnmValue
const *b
,
1004 GnmExpr
const *expr
)
1006 GnmValue
*res
, *va
, *vb
;
1008 if (a
!= NULL
&& VALUE_IS_ERROR (a
))
1009 return value_dup (a
);
1010 if (b
!= NULL
&& VALUE_IS_ERROR (b
))
1011 return value_dup (b
);
1012 if (VALUE_IS_EMPTY (a
))
1013 a
= va
= (GnmValue
*)value_zero
;
1014 else if (VALUE_IS_STRING (a
)) {
1015 va
= format_match_number (value_peek_string (a
), NULL
,
1016 sheet_date_conv (ep
->sheet
));
1018 return value_new_error_VALUE (ep
);
1019 } else if (!VALUE_IS_NUMBER (a
))
1020 return value_new_error_VALUE (ep
);
1023 if (VALUE_IS_EMPTY (b
))
1024 b
= vb
= (GnmValue
*)value_zero
;
1025 else if (VALUE_IS_STRING (b
)) {
1026 vb
= format_match_number (value_peek_string (b
), NULL
,
1027 sheet_date_conv (ep
->sheet
));
1031 return value_new_error_VALUE (ep
);
1033 } else if (!VALUE_IS_NUMBER (b
)) {
1036 return value_new_error_VALUE (ep
);
1040 res
= bin_arith (expr
, ep
, va
, vb
);
1049 cb_bin_cat (GnmEvalPos
const *ep
, GnmValue
const *a
, GnmValue
const *b
,
1050 GnmExpr
const *expr
)
1052 if (a
!= NULL
&& VALUE_IS_ERROR (a
))
1053 return value_dup (a
);
1054 if (b
!= NULL
&& VALUE_IS_ERROR (b
))
1055 return value_dup (b
);
1058 return value_new_string (value_peek_string (b
));
1060 return value_new_string ("");
1061 } else if (b
== NULL
)
1062 return value_new_string (value_peek_string (a
));
1064 char *tmp
= g_strconcat (value_peek_string (a
),
1065 value_peek_string (b
), NULL
);
1066 return value_new_string_nocopy (tmp
);
1070 typedef GnmValue
*(*BinOpImplicitIteratorFunc
) (GnmEvalPos
const *ep
,
1073 gpointer user_data
);
1075 GnmEvalPos
const *ep
;
1077 GnmValue
const *a
, *b
;
1078 BinOpImplicitIteratorFunc func
;
1080 /* multiply by 0 in unused dimensions.
1081 * this is simpler than lots of conditions
1082 * state->use_x.a ? x : 0
1088 } BinOpImplicitIteratorState
;
1091 cb_implicit_iter_a_and_b (GnmValueIter
const *v_iter
,
1092 BinOpImplicitIteratorState
const *state
)
1094 state
->res
->v_array
.vals
[v_iter
->x
][v_iter
->y
] =
1095 (*state
->func
) (v_iter
->ep
,
1096 value_area_get_x_y (state
->a
,
1097 state
->x
.a
* v_iter
->x
,
1098 state
->y
.a
* v_iter
->y
, v_iter
->ep
),
1099 value_area_get_x_y (state
->b
,
1100 state
->x
.b
* v_iter
->x
,
1101 state
->y
.b
* v_iter
->y
, v_iter
->ep
),
1106 cb_implicit_iter_a_to_scalar_b (GnmValueIter
const *v_iter
,
1107 BinOpImplicitIteratorState
const *state
)
1109 state
->res
->v_array
.vals
[v_iter
->x
][v_iter
->y
] =
1110 (*state
->func
) (v_iter
->ep
,
1111 v_iter
->v
, state
->b
, state
->user_data
);
1115 /* This is only triggered if something returns an array or a range which can
1116 * only happen if we are in array eval mode. */
1118 bin_array_iter_a (GnmEvalPos
const *ep
,
1119 GnmValue
*a
, GnmValue
*b
,
1120 BinOpImplicitIteratorFunc func
,
1121 GnmExpr
const *expr
)
1123 BinOpImplicitIteratorState iter_info
;
1125 /* a must be a cellrange or array, it can not be NULL */
1127 iter_info
.func
= func
;
1128 iter_info
.user_data
= (gpointer
) expr
;
1133 * Use matching positions unless the dimension is singular, in which
1134 * case use the zero item
1135 * res[x][y] = f(a[singular.a.x ? 0 : x, b[singular.b.x ? 0 : x)
1137 * If both items have non-singular sizes for
1138 * the same dimension use the min size (see samples/array.xls) */
1140 (VALUE_IS_CELLRANGE (b
) || VALUE_IS_ARRAY (b
))) {
1141 int sa
, sb
, w
= 1, h
= 1;
1143 sa
= value_area_get_width (a
, ep
);
1144 sb
= value_area_get_width (b
, ep
);
1145 if ((iter_info
.x
.a
= (sa
== 1) ? 0 : 1))
1147 if ((iter_info
.x
.b
= (sb
== 1) ? 0 : 1) && (w
> sb
|| w
== 1))
1150 sa
= value_area_get_height (a
, ep
);
1151 sb
= value_area_get_height (b
, ep
);
1152 if ((iter_info
.y
.a
= (sa
== 1) ? 0 : 1))
1154 if ((iter_info
.y
.b
= (sb
== 1) ? 0 : 1) && (h
> sb
|| h
== 1))
1157 iter_info
.res
= value_new_array_empty (w
, h
);
1158 value_area_foreach (iter_info
.res
, ep
, CELL_ITER_ALL
,
1159 (GnmValueIterFunc
) cb_implicit_iter_a_and_b
, &iter_info
);
1161 iter_info
.res
= value_new_array_empty (
1162 value_area_get_width (a
, ep
),
1163 value_area_get_height (a
, ep
));
1164 value_area_foreach (a
, ep
, CELL_ITER_ALL
,
1165 (GnmValueIterFunc
) cb_implicit_iter_a_to_scalar_b
, &iter_info
);
1170 return iter_info
.res
;
1174 cb_implicit_iter_b_to_scalar_a (GnmValueIter
const *v_iter
,
1175 BinOpImplicitIteratorState
const *state
)
1177 state
->res
->v_array
.vals
[v_iter
->x
][v_iter
->y
] =
1178 (*state
->func
) (v_iter
->ep
,
1179 state
->a
, v_iter
->v
, state
->user_data
);
1183 bin_array_iter_b (GnmEvalPos
const *ep
,
1184 GnmValue
*a
, GnmValue
*b
,
1185 BinOpImplicitIteratorFunc func
,
1186 GnmExpr
const *expr
)
1188 BinOpImplicitIteratorState iter_info
;
1190 iter_info
.func
= func
;
1191 iter_info
.user_data
= (gpointer
) expr
;
1195 /* b must be a cellrange or array, it cannot be NULL */
1196 iter_info
.res
= value_new_array_empty (
1197 value_area_get_width (b
, ep
),
1198 value_area_get_height (b
, ep
));
1199 value_area_foreach (b
, ep
, CELL_ITER_ALL
,
1200 (GnmValueIterFunc
) cb_implicit_iter_b_to_scalar_a
, &iter_info
);
1204 return iter_info
.res
;
1208 negate_value (GnmValue
const *v
)
1210 if (VALUE_IS_NUMBER (v
)) {
1211 GnmValue
*tmp
= value_new_float (0 - value_get_as_float (v
));
1212 value_set_fmt (tmp
, VALUE_FMT (v
));
1219 cb_iter_unary_neg (GnmValueIter
const *v_iter
, GnmValue
*res
)
1221 GnmValue
const *v
= v_iter
->v
;
1222 GnmValue
*tmp
= NULL
;
1224 if (VALUE_IS_EMPTY (v
))
1225 tmp
= value_new_int (0);
1226 else if (VALUE_IS_ERROR (v
))
1227 tmp
= value_dup (v
);
1228 else if (VALUE_IS_STRING (v
)) {
1229 GnmValue
*conv
= format_match_number (
1230 value_peek_string (v
), NULL
,
1231 sheet_date_conv (v_iter
->ep
->sheet
));
1233 tmp
= negate_value (conv
);
1234 value_release (conv
);
1237 /* BOOL goes here. */
1238 tmp
= negate_value (v
);
1242 tmp
= value_new_error_VALUE (v_iter
->ep
);
1243 res
->v_array
.vals
[v_iter
->x
][v_iter
->y
] = tmp
;
1248 cb_iter_percentage (GnmValueIter
const *v_iter
, GnmValue
*res
)
1250 GnmValue
const *v
= v_iter
->v
;
1253 if (VALUE_IS_EMPTY (v
))
1254 tmp
= value_new_int (0);
1255 else if (VALUE_IS_ERROR (v
))
1256 tmp
= value_dup (v
);
1258 GnmValue
*conv
= NULL
;
1259 if (VALUE_IS_STRING (v
)) {
1260 conv
= format_match_number (
1261 value_peek_string (v
), NULL
,
1262 sheet_date_conv (v_iter
->ep
->sheet
));
1267 if (VALUE_IS_NUMBER (v
)){
1268 tmp
= value_new_float (value_get_as_float (v
) / 100);
1269 value_set_fmt (tmp
, go_format_default_percentage ());
1271 tmp
= value_new_error_VALUE (v_iter
->ep
);
1273 value_release (conv
);
1276 res
->v_array
.vals
[v_iter
->x
][v_iter
->y
] = tmp
;
1281 gnm_expr_range_op (GnmExpr
const *expr
, GnmEvalPos
const *ep
,
1282 GnmExprEvalFlags flags
)
1284 GnmRangeRef a_ref
, b_ref
;
1285 GnmRange a_range
, b_range
, res_range
;
1286 Sheet
*a_start
, *a_end
, *b_start
, *b_end
;
1287 GnmValue
*res
= NULL
;
1289 if (gnm_expr_extract_ref (&a_ref
, expr
->binary
.value_a
, ep
, flags
) ||
1290 gnm_expr_extract_ref (&b_ref
, expr
->binary
.value_b
, ep
, flags
))
1291 return value_new_error_REF (ep
);
1293 gnm_rangeref_normalize (&a_ref
, ep
, &a_start
, &a_end
, &a_range
);
1294 gnm_rangeref_normalize (&b_ref
, ep
, &b_start
, &b_end
, &b_range
);
1296 switch (GNM_EXPR_GET_OPER (expr
)) {
1297 case GNM_EXPR_OP_RANGE_CTOR
:
1298 res_range
= range_union (&a_range
, &b_range
);
1299 /* b_range might be on a bigger sheet. */
1300 range_ensure_sanity (&res_range
, a_start
);
1302 case GNM_EXPR_OP_INTERSECT
:
1303 /* 3D references not allowed. */
1304 if (a_start
!= a_end
|| b_start
!= b_end
)
1305 return value_new_error_VALUE (ep
);
1307 /* Must be same sheet. */
1308 if (a_start
!= b_start
)
1309 return value_new_error_VALUE (ep
);
1311 if (!range_intersection (&res_range
, &a_range
, &b_range
))
1312 return value_new_error_NULL (ep
);
1315 g_assert_not_reached ();
1319 res
= value_new_cellrange_r (a_start
, &res_range
);
1320 dependent_add_dynamic_dep (ep
->dep
, &res
->v_range
.cell
);
1321 if (!(flags
& GNM_EXPR_EVAL_PERMIT_NON_SCALAR
)) {
1322 res
= value_intersection (res
, ep
);
1323 return (res
!= NULL
)
1324 ? handle_empty (res
, flags
)
1325 : value_new_error_VALUE (ep
);
1333 * @pos: evaluation position
1334 * @flags: #GnmExprEvalFlags
1336 * Evaluatates the given expression. Iif GNM_EXPR_EVAL_PERMIT_EMPTY is not set
1337 * then return zero if the expression instead of the empty value, or the value
1338 * of an unused cell.
1340 * Returns: (transfer full): result.
1343 gnm_expr_eval (GnmExpr
const *expr
, GnmEvalPos
const *pos
,
1344 GnmExprEvalFlags flags
)
1346 GnmValue
*res
= NULL
, *a
= NULL
, *b
= NULL
;
1348 g_return_val_if_fail (expr
!= NULL
, handle_empty (NULL
, flags
));
1349 g_return_val_if_fail (pos
!= NULL
, handle_empty (NULL
, flags
));
1352 switch (GNM_EXPR_GET_OPER (expr
)){
1353 case GNM_EXPR_OP_EQUAL
:
1354 case GNM_EXPR_OP_NOT_EQUAL
:
1355 case GNM_EXPR_OP_GT
:
1356 case GNM_EXPR_OP_GTE
:
1357 case GNM_EXPR_OP_LT
:
1358 case GNM_EXPR_OP_LTE
:
1359 flags
|= GNM_EXPR_EVAL_PERMIT_EMPTY
;
1360 flags
&= ~GNM_EXPR_EVAL_WANT_REF
;
1362 a
= gnm_expr_eval (expr
->binary
.value_a
, pos
, flags
);
1364 if (VALUE_IS_ERROR (a
))
1366 if (VALUE_IS_CELLRANGE (a
) || VALUE_IS_ARRAY (a
))
1367 return bin_array_iter_a (pos
, a
,
1368 gnm_expr_eval (expr
->binary
.value_b
, pos
, flags
),
1369 (BinOpImplicitIteratorFunc
) cb_bin_cmp
,
1373 b
= gnm_expr_eval (expr
->binary
.value_b
, pos
, flags
);
1375 if (VALUE_IS_ERROR (b
)) {
1379 if (VALUE_IS_CELLRANGE (b
) || VALUE_IS_ARRAY (b
))
1380 return bin_array_iter_b (pos
, a
, b
,
1381 (BinOpImplicitIteratorFunc
) cb_bin_cmp
,
1385 res
= bin_cmp (GNM_EXPR_GET_OPER (expr
), value_compare (a
, b
, FALSE
), pos
);
1390 case GNM_EXPR_OP_ADD
:
1391 case GNM_EXPR_OP_SUB
:
1392 case GNM_EXPR_OP_MULT
:
1393 case GNM_EXPR_OP_DIV
:
1394 case GNM_EXPR_OP_EXP
:
1398 * 2) #!VALUE error if A is not a number
1400 * 4) #!VALUE error if B is not a number
1401 * 5) result of operation, or error specific to the operation
1404 /* Guarantees value != NULL */
1405 flags
&= ~GNM_EXPR_EVAL_PERMIT_EMPTY
;
1406 flags
&= ~GNM_EXPR_EVAL_WANT_REF
;
1408 /* 1) Error from A */
1409 a
= gnm_expr_eval (expr
->binary
.value_a
, pos
, flags
);
1410 if (VALUE_IS_ERROR (a
))
1411 return value_error_set_pos (&a
->v_err
, pos
);
1413 /* 2) #!VALUE error if A is not a number */
1414 if (VALUE_IS_STRING (a
)) {
1415 GnmValue
*tmp
= format_match_number (value_peek_string (a
), NULL
,
1416 sheet_date_conv (pos
->sheet
));
1420 return value_new_error_VALUE (pos
);
1422 } else if (VALUE_IS_CELLRANGE (a
) || VALUE_IS_ARRAY (a
)) {
1423 b
= gnm_expr_eval (expr
->binary
.value_b
, pos
, flags
);
1424 if (VALUE_IS_STRING (b
)) {
1425 res
= format_match_number (value_peek_string (b
), NULL
,
1426 sheet_date_conv (pos
->sheet
));
1428 b
= (res
== NULL
) ? value_new_error_VALUE (pos
) : res
;
1430 return bin_array_iter_a (pos
, a
, b
,
1431 (BinOpImplicitIteratorFunc
) cb_bin_arith
,
1433 } else if (!VALUE_IS_NUMBER (a
)) {
1435 return value_new_error_VALUE (pos
);
1438 /* 3) Error from B */
1439 b
= gnm_expr_eval (expr
->binary
.value_b
, pos
, flags
);
1440 if (VALUE_IS_ERROR (b
)) {
1442 return value_error_set_pos (&b
->v_err
, pos
);
1445 /* 4) #!VALUE error if B is not a number */
1446 if (VALUE_IS_STRING (b
)) {
1447 GnmValue
*tmp
= format_match_number (value_peek_string (b
), NULL
,
1448 sheet_date_conv (pos
->sheet
));
1453 return value_new_error_VALUE (pos
);
1456 } else if (VALUE_IS_CELLRANGE (b
) || VALUE_IS_ARRAY (b
))
1457 return bin_array_iter_b (pos
, a
, b
,
1458 (BinOpImplicitIteratorFunc
) cb_bin_arith
,
1460 else if (!VALUE_IS_NUMBER (b
)) {
1463 return value_new_error_VALUE (pos
);
1466 res
= bin_arith (expr
, pos
, a
, b
);
1471 case GNM_EXPR_OP_PAREN
:
1472 /* Avoid recursive call to save stack. */
1473 expr
= expr
->unary
.value
;
1476 case GNM_EXPR_OP_PERCENTAGE
:
1477 case GNM_EXPR_OP_UNARY_NEG
:
1478 case GNM_EXPR_OP_UNARY_PLUS
:
1479 /* Guarantees value != NULL */
1480 flags
&= ~GNM_EXPR_EVAL_PERMIT_EMPTY
;
1481 flags
&= ~GNM_EXPR_EVAL_WANT_REF
;
1483 a
= gnm_expr_eval (expr
->unary
.value
, pos
, flags
);
1484 if (VALUE_IS_ERROR (a
))
1486 if (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_UNARY_PLUS
)
1489 /* 2) #!VALUE error if A is not a number */
1490 if (VALUE_IS_STRING (a
)) {
1491 GnmValue
*tmp
= format_match_number (value_peek_string (a
), NULL
,
1492 sheet_date_conv (pos
->sheet
));
1496 return value_new_error_VALUE (pos
);
1498 } else if (VALUE_IS_CELLRANGE (a
) || VALUE_IS_ARRAY (a
)) {
1499 res
= value_new_array_empty (
1500 value_area_get_width (a
, pos
),
1501 value_area_get_height (a
, pos
));
1502 value_area_foreach (a
, pos
, CELL_ITER_ALL
,
1503 (GnmValueIterFunc
) ((GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_UNARY_NEG
)
1504 ? cb_iter_unary_neg
: cb_iter_percentage
),
1509 if (!VALUE_IS_NUMBER (a
))
1510 res
= value_new_error_VALUE (pos
);
1511 else if (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_UNARY_NEG
)
1512 res
= negate_value (a
);
1514 res
= value_new_float (value_get_as_float (a
) / 100);
1515 value_set_fmt (res
, go_format_default_percentage ());
1520 case GNM_EXPR_OP_CAT
:
1521 flags
|= GNM_EXPR_EVAL_PERMIT_EMPTY
;
1522 flags
&= ~GNM_EXPR_EVAL_WANT_REF
;
1523 a
= gnm_expr_eval (expr
->binary
.value_a
, pos
, flags
);
1525 if (VALUE_IS_ERROR (a
))
1527 if (VALUE_IS_CELLRANGE (a
) || VALUE_IS_ARRAY (a
))
1528 return bin_array_iter_a (pos
, a
,
1529 gnm_expr_eval (expr
->binary
.value_b
, pos
, flags
),
1530 (BinOpImplicitIteratorFunc
) cb_bin_cat
,
1533 b
= gnm_expr_eval (expr
->binary
.value_b
, pos
, flags
);
1535 if (VALUE_IS_ERROR (b
)) {
1539 if (VALUE_IS_CELLRANGE (b
) || VALUE_IS_ARRAY (b
))
1540 return bin_array_iter_b (pos
, a
, b
,
1541 (BinOpImplicitIteratorFunc
) cb_bin_cat
,
1547 res
= value_new_string (value_peek_string (b
));
1550 res
= value_new_string ("");
1551 } else if (b
== NULL
) {
1552 res
= value_new_string (value_peek_string (a
));
1555 char *tmp
= g_strconcat (value_peek_string (a
),
1556 value_peek_string (b
), NULL
);
1557 res
= value_new_string_nocopy (tmp
);
1563 case GNM_EXPR_OP_FUNCALL
: {
1566 ei
.func_call
= &expr
->func
;
1568 res
= function_call_with_exprs (&ei
);
1570 return (flags
& GNM_EXPR_EVAL_PERMIT_EMPTY
)
1571 ? NULL
: value_new_int (0);
1572 if (VALUE_IS_CELLRANGE (res
)) {
1574 * pos->dep really shouldn't be NULL here, but it
1575 * will be if someone puts "indirect" into an
1576 * expression used for conditional formats.
1579 dependent_add_dynamic_dep (pos
->dep
,
1580 &res
->v_range
.cell
);
1581 if (!(flags
& GNM_EXPR_EVAL_PERMIT_NON_SCALAR
)) {
1582 res
= value_intersection (res
, pos
);
1583 return (res
!= NULL
)
1584 ? handle_empty (res
, flags
)
1585 : value_new_error_VALUE (pos
);
1589 if (VALUE_IS_ARRAY (res
) &&
1590 !(flags
& GNM_EXPR_EVAL_PERMIT_NON_SCALAR
)) {
1591 a
= (res
->v_array
.x
> 0 && res
->v_array
.y
> 0)
1592 ? value_dup (res
->v_array
.vals
[0][0])
1593 : value_new_error_REF (pos
);
1594 value_release (res
);
1600 case GNM_EXPR_OP_NAME
:
1601 if (expr_name_is_active (expr
->name
.name
))
1602 return handle_empty (expr_name_eval (expr
->name
.name
, pos
, flags
), flags
);
1603 return value_new_error_REF (pos
);
1605 case GNM_EXPR_OP_CELLREF
: {
1609 gnm_cellref_make_abs (&r
, &expr
->cellref
.ref
, pos
);
1611 cell
= sheet_cell_get (eval_sheet (r
.sheet
, pos
->sheet
),
1614 gnm_cell_eval (cell
);
1616 if (flags
& GNM_EXPR_EVAL_WANT_REF
) {
1617 return value_new_cellrange_unsafe (&r
, &r
);
1619 GnmValue
*v
= cell
? value_dup (cell
->value
) : NULL
;
1620 return handle_empty (v
, flags
);
1624 case GNM_EXPR_OP_CONSTANT
:
1625 res
= value_dup (expr
->constant
.value
);
1626 if (VALUE_IS_CELLRANGE (res
) || VALUE_IS_ARRAY (res
)) {
1627 if (flags
& GNM_EXPR_EVAL_PERMIT_NON_SCALAR
)
1629 res
= value_intersection (res
, pos
);
1630 return (res
!= NULL
)
1631 ? handle_empty (res
, flags
)
1632 : value_new_error_VALUE (pos
);
1634 return handle_empty (res
, flags
);
1636 case GNM_EXPR_OP_ARRAY_CORNER
:
1637 case GNM_EXPR_OP_ARRAY_ELEM
:
1638 g_warning ("Unexpected array expressions encountered");
1639 return value_new_error_VALUE (pos
);
1641 case GNM_EXPR_OP_SET
:
1642 if (flags
& GNM_EXPR_EVAL_PERMIT_NON_SCALAR
) {
1644 int argc
= expr
->set
.argc
;
1646 res
= value_new_array_non_init (1, expr
->set
.argc
);
1647 res
->v_array
.vals
[0] = g_new (GnmValue
*, expr
->set
.argc
);
1648 for (i
= 0; i
< argc
; i
++)
1649 res
->v_array
.vals
[0][i
] = gnm_expr_eval (
1650 expr
->set
.argv
[i
], pos
,
1651 GNM_EXPR_EVAL_SCALAR_NON_EMPTY
);
1654 return value_new_error_VALUE (pos
);
1656 case GNM_EXPR_OP_RANGE_CTOR
:
1657 case GNM_EXPR_OP_INTERSECT
:
1658 return gnm_expr_range_op (expr
, pos
, flags
);
1661 g_assert_not_reached ();
1662 return value_new_error (pos
, _("Unknown evaluation error"));
1666 * gnm_expr_simplify_if:
1669 * Simplifies @expr if it is a call to "if" with a constant condition.
1671 * Returns: (transfer full) (nullable): simpler expression.
1674 gnm_expr_simplify_if (GnmExpr
const *expr
)
1676 static GnmFunc
*f_if
= NULL
;
1677 GnmExpr
const *cond
;
1680 g_return_val_if_fail (expr
!= NULL
, NULL
);
1682 if (GNM_EXPR_GET_OPER (expr
) != GNM_EXPR_OP_FUNCALL
)
1686 f_if
= gnm_func_lookup ("if", NULL
);
1688 if (expr
->func
.func
!= f_if
|| expr
->func
.argc
!= 3)
1691 cond
= expr
->func
.argv
[0];
1692 if (GNM_EXPR_GET_OPER (cond
) == GNM_EXPR_OP_CONSTANT
) {
1693 GnmValue
const *condval
= cond
->constant
.value
;
1695 c
= value_get_as_bool (condval
, &err
);
1701 // We used to test for true() and false() as conditions too, but the code
1702 // never worked and has been unreachable until now.
1704 return gnm_expr_copy (expr
->func
.argv
[c
? 1 : 2]);
1710 * Converts a parsed tree into its string representation
1711 * assuming that we are evaluating at col, row
1713 * This routine is pretty simple: it walks the GnmExpr and
1714 * appends a string representation to the target.
1717 do_expr_as_string (GnmExpr
const *expr
, int paren_level
,
1718 GnmConventionsOut
*out
)
1722 guint8 prec
; /* Precedences -- should match parser.y */
1723 guint8 assoc_left
, assoc_right
; /* 0: no, 1: yes. */
1724 guint8 is_prefix
; /* for unary operators */
1725 } const operations
[] = {
1726 { "", 0, 0, 0, 0 }, /* Parentheses for clarity */
1727 { "=", 1, 1, 0, 0 },
1728 { ">", 1, 1, 0, 0 },
1729 { "<", 1, 1, 0, 0 },
1730 { ">=", 1, 1, 0, 0 },
1731 { "<=", 1, 1, 0, 0 },
1732 { "<>", 1, 1, 0, 0 },
1733 { "+", 3, 1, 0, 0 },
1734 { "-", 3, 1, 0, 0 },
1735 { "*", 4, 1, 0, 0 },
1736 { "/", 4, 1, 0, 0 },
1737 { "^", 5, 0, 0, 0 }, /* Note: neither left nor right */
1738 { "&", 2, 1, 0, 0 },
1739 { "", 0, 0, 0, 0 }, /* Funcall */
1740 { "", 0, 0, 0, 0 }, /* Name */
1741 { "", 0, 0, 0, 0 }, /* Constant */
1742 { "", 0, 0, 0, 0 }, /* Var */
1743 { "-", 7, 0, 0, 1 }, /* Unary - */
1744 { "+", 7, 0, 0, 1 }, /* Unary + */
1745 { "%", 6, 0, 0, 0 }, /* Percentage (NOT MODULO) */
1746 { "", 0, 0, 0, 0 }, /* ArrayCorner */
1747 { "", 0, 0, 0, 0 }, /* ArrayElem */
1748 { "", 8, 0, 0, 0 }, /* Set */
1749 { ":", 10, 1, 0, 0 }, /* Range Ctor */
1750 { " ", 9, 1, 0, 0 } /* Intersection */
1752 GnmExprOp
const op
= GNM_EXPR_GET_OPER (expr
);
1753 GString
*target
= out
->accum
;
1756 case GNM_EXPR_OP_RANGE_CTOR
:
1757 case GNM_EXPR_OP_INTERSECT
:
1758 case GNM_EXPR_OP_ANY_BINARY
: {
1759 char const *opname
= operations
[op
].name
;
1760 int prec
= operations
[op
].prec
;
1761 gboolean need_par
= (prec
<= paren_level
);
1762 size_t prelen
= target
->len
;
1764 if (need_par
) g_string_append_c (target
, '(');
1765 do_expr_as_string (expr
->binary
.value_a
,
1766 prec
- operations
[op
].assoc_left
, out
);
1769 * Avoid getting "-2^2". We want to make sure files do not
1770 * contain that construct as we might later change precedence.
1772 * Always produce either "-(2^2)" or "(-2)^2".
1774 * Note, that the parser introduces an explicit parenthesis in
1775 * this case also, so parsed expressions should not be
1776 * affected by the code here.
1778 if (op
== GNM_EXPR_OP_EXP
&&
1779 (target
->str
[prelen
] == '-' || target
->str
[prelen
] == '+')) {
1780 g_string_insert_c (target
, prelen
, '(');
1781 g_string_append_c (target
, ')');
1784 /* Instead of this we ought to move the whole operations
1785 table into the conventions. */
1786 if (op
== GNM_EXPR_OP_INTERSECT
)
1787 g_string_append_unichar (target
, out
->convs
->intersection_char
);
1789 g_string_append (target
, opname
);
1791 do_expr_as_string (expr
->binary
.value_b
,
1792 prec
- operations
[op
].assoc_right
, out
);
1793 if (need_par
) g_string_append_c (target
, ')');
1797 case GNM_EXPR_OP_ANY_UNARY
: {
1798 char const *opname
= operations
[op
].name
;
1799 int prec
= operations
[op
].prec
;
1800 gboolean is_prefix
= operations
[op
].is_prefix
;
1801 gboolean need_par
= (prec
<= paren_level
);
1803 if (need_par
) g_string_append_c (target
, '(');
1804 if (is_prefix
) g_string_append (target
, opname
);
1805 do_expr_as_string (expr
->unary
.value
, prec
, out
);
1806 if (!is_prefix
) g_string_append (target
, opname
);
1807 if (need_par
) g_string_append_c (target
, ')');
1811 case GNM_EXPR_OP_FUNCALL
:
1812 out
->convs
->output
.func (out
, &expr
->func
);
1815 case GNM_EXPR_OP_NAME
:
1816 out
->convs
->output
.name (out
, &expr
->name
);
1819 case GNM_EXPR_OP_CELLREF
:
1820 out
->convs
->output
.cell_ref (out
, &expr
->cellref
.ref
, FALSE
);
1823 case GNM_EXPR_OP_CONSTANT
: {
1824 GnmValue
const *v
= expr
->constant
.value
;
1825 size_t prelen
= target
->len
;
1827 if (VALUE_IS_STRING (v
)) {
1828 out
->convs
->output
.string (out
, v
->v_str
.val
);
1832 if (VALUE_IS_CELLRANGE (v
)) {
1833 out
->convs
->output
.range_ref (out
, &v
->v_range
.cell
);
1837 if (VALUE_IS_BOOLEAN (v
) &&
1838 out
->convs
->output
.boolean
!= NULL
) {
1839 out
->convs
->output
.boolean (out
, v
->v_bool
.val
);
1844 value_get_as_gstring (v
, target
, out
->convs
);
1846 /* If the number has a sign, pretend that it is the result of
1847 * OPER_UNARY_{NEG,PLUS}.
1849 if ((target
->str
[prelen
] == '-' || target
->str
[prelen
] == '+') &&
1850 operations
[GNM_EXPR_OP_UNARY_NEG
].prec
<= paren_level
) {
1851 g_string_insert_c (target
, prelen
, '(');
1852 g_string_append_c (target
, ')');
1857 case GNM_EXPR_OP_ARRAY_CORNER
:
1858 do_expr_as_string (expr
->array_corner
.expr
, 0, out
);
1861 case GNM_EXPR_OP_ARRAY_ELEM
: {
1862 GnmCell
const *corner
= array_elem_get_corner (&expr
->array_elem
,
1863 out
->pp
->sheet
, &out
->pp
->eval
);
1864 if (NULL
!= corner
) {
1865 GnmParsePos
const *real_pp
= out
->pp
;
1866 GnmParsePos pp
= *real_pp
;
1868 pp
.eval
.col
-= expr
->array_elem
.x
;
1869 pp
.eval
.row
-= expr
->array_elem
.y
;
1872 corner
->base
.texpr
->expr
->array_corner
.expr
,
1880 case GNM_EXPR_OP_SET
:
1881 gnm_expr_list_as_string (expr
->set
.argc
, expr
->set
.argv
, out
);
1885 g_string_append (target
, "<ERROR>");
1889 * gnm_expr_as_gstring:
1891 * @out: output convensions
1893 * Renders the expression as a string according to @out and places the
1894 * result in @out's accumulator.
1897 gnm_expr_as_gstring (GnmExpr
const *expr
, GnmConventionsOut
*out
)
1899 g_return_if_fail (expr
!= NULL
);
1900 g_return_if_fail (out
!= NULL
);
1902 do_expr_as_string (expr
, 0, out
);
1906 * gnm_expr_as_string:
1908 * @pp: (nullable): Parse position. %NULL should be used for debugging only.
1909 * @convs: (nullable): #GnmConventions. %NULL should be used for debugging
1910 * or when @pp identifies a #Sheet.
1912 * Renders the expression as a string according to @convs.
1914 * Returns: (transfer full): @expr as a string.
1917 gnm_expr_as_string (GnmExpr
const *expr
, GnmParsePos
const *pp
,
1918 GnmConventions
const *convs
)
1920 GnmConventionsOut out
;
1923 g_return_val_if_fail (expr
!= NULL
, NULL
);
1926 * Defaults for debugging only!
1929 /* UGH: Just get the first sheet in the first workbook! */
1930 Workbook
*wb
= gnm_app_workbook_get_by_index (0);
1931 Sheet
*sheet
= workbook_sheet_by_index (wb
, 0);
1932 parse_pos_init (&pp0
, NULL
, sheet
, 0, 0);
1937 ? sheet_get_conventions (pp
->sheet
)
1938 : gnm_conventions_default
;
1940 out
.accum
= g_string_new (NULL
);
1943 do_expr_as_string (expr
, 0, &out
);
1944 return g_string_free (out
.accum
, FALSE
);
1947 /****************************************************************************/
1950 gnm_expr_is_err (GnmExpr
const *expr
, GnmStdError err
)
1954 if (GNM_EXPR_GET_OPER (expr
) != GNM_EXPR_OP_CONSTANT
)
1957 err2
= value_error_classify (expr
->constant
.value
);
1962 * gnm_expr_get_constant:
1965 * Returns: (transfer none) (nullable): If this expression consists of just
1966 * a constant, return it. Otherwise, %NULL.
1969 gnm_expr_get_constant (GnmExpr
const *expr
)
1971 if (GNM_EXPR_GET_OPER (expr
) != GNM_EXPR_OP_CONSTANT
)
1974 return expr
->constant
.value
;
1978 * gnm_expr_get_name:
1981 * Returns: (transfer none) (nullable): If this expression consists of just
1982 * a name, return it. Otherwise, %NULL.
1984 GnmNamedExpr
const *
1985 gnm_expr_get_name (GnmExpr
const *expr
)
1987 if (GNM_EXPR_GET_OPER (expr
) != GNM_EXPR_OP_NAME
)
1990 return expr
->name
.name
;
1995 * gnm_expr_get_cellref:
1998 * Returns: (transfer none) (nullable): If this expression consists of just
1999 * a cell reference, return it. Otherwise, %NULL.
2002 gnm_expr_get_cellref (GnmExpr
const *expr
)
2004 if (GNM_EXPR_GET_OPER (expr
) != GNM_EXPR_OP_CELLREF
)
2007 return &expr
->cellref
.ref
;
2012 GnmExprRelocateInfo
const *details
;
2013 gboolean from_inside
;
2014 gboolean check_rels
;
2015 } RelocInfoInternal
;
2017 static GnmExpr
const *
2018 invalidate_sheet_cellrange (RelocInfoInternal
const *rinfo
,
2019 GnmValueRange
const *v
)
2021 GnmCellRef ref_a
= v
->cell
.a
;
2022 GnmCellRef ref_b
= v
->cell
.b
;
2024 Sheet
const *sheet_a
= ref_a
.sheet
;
2025 Sheet
const *sheet_b
= ref_b
.sheet
;
2027 gboolean hit_a
= sheet_a
&& sheet_a
->being_invalidated
;
2028 gboolean hit_b
= sheet_b
&& sheet_b
->being_invalidated
;
2031 if (!hit_a
&& !hit_b
)
2034 if (sheet_a
== NULL
|| sheet_b
== NULL
||
2035 sheet_a
->workbook
!= sheet_b
->workbook
)
2036 /* A 3D reference between workbooks? */
2037 return gnm_expr_new_constant (value_new_error_REF (NULL
));
2039 /* Narrow the sheet range. */
2040 wb
= sheet_a
->workbook
;
2041 dir
= (sheet_a
->index_in_wb
< sheet_b
->index_in_wb
) ? +1 : -1;
2042 while (sheet_a
!= sheet_b
&& sheet_a
->being_invalidated
)
2043 sheet_a
= workbook_sheet_by_index (wb
, sheet_a
->index_in_wb
+ dir
);
2044 while (sheet_a
!= sheet_b
&& sheet_b
->being_invalidated
)
2045 sheet_b
= workbook_sheet_by_index (wb
, sheet_b
->index_in_wb
- dir
);
2047 if (sheet_a
->being_invalidated
)
2048 return gnm_expr_new_constant (value_new_error_REF (NULL
));
2050 ref_a
.sheet
= (Sheet
*)sheet_a
;
2051 ref_b
.sheet
= (Sheet
*)sheet_b
;
2052 return gnm_expr_new_constant (value_new_cellrange_unsafe (&ref_a
, &ref_b
));
2056 reloc_range (GnmExprRelocateInfo
const *rinfo
,
2057 Sheet
const *start_sheet
, Sheet
const *end_sheet
,
2060 GnmRange t
, b
, l
, r
;
2061 gboolean start
, end
;
2063 if (start_sheet
!= end_sheet
|| /* ignore 3d refs */
2064 start_sheet
!= rinfo
->origin_sheet
) /* ref is to a different sheet */
2067 t
.start
.col
= b
.start
.col
= l
.start
.col
= l
.end
.col
= rng
->start
.col
;
2068 t
.end
.col
= b
.end
.col
= r
.start
.col
= r
.end
.col
= rng
->end
.col
;
2069 t
.start
.row
= t
.end
.row
= l
.start
.row
= r
.start
.row
= rng
->start
.row
;
2070 b
.start
.row
= b
.end
.row
= l
.end
.row
= r
.end
.row
= rng
->end
.row
;
2072 start
= range_contained (&t
, &rinfo
->origin
);
2073 end
= range_contained (&b
, &rinfo
->origin
);
2074 if (start
&& end
) { /* full enclosure */
2075 rng
->start
.col
+= rinfo
->col_offset
;
2076 rng
->end
.col
+= rinfo
->col_offset
;
2077 rng
->start
.row
+= rinfo
->row_offset
;
2078 rng
->end
.row
+= rinfo
->row_offset
;
2082 if (rinfo
->col_offset
== 0) {
2083 if (start
&& rinfo
->row_offset
< range_height (rng
)) {
2084 rng
->start
.row
+= rinfo
->row_offset
;
2087 if (end
&& rinfo
->row_offset
> -range_height (rng
)) {
2088 /* Special case invalidating the bottom of a range while
2089 * deleting rows. Otherwise we #REF! before we can shorten
2090 * The -1 is safe, origin.start.row == 0 is handled above */
2091 if (rinfo
->reloc_type
== GNM_EXPR_RELOCATE_ROWS
&&
2092 rinfo
->row_offset
>= gnm_sheet_get_max_rows (end_sheet
))
2093 rng
->end
.row
= rinfo
->origin
.start
.row
- 1;
2095 rng
->end
.row
+= rinfo
->row_offset
;
2100 if (rinfo
->row_offset
== 0) {
2101 if (range_contained (&l
, &rinfo
->origin
) &&
2102 rinfo
->col_offset
< range_width (rng
)) {
2103 rng
->start
.col
+= rinfo
->col_offset
;
2106 if (range_contained (&r
, &rinfo
->origin
) &&
2107 rinfo
->col_offset
> -range_width (rng
)) {
2108 /* Special case invalidating the right side of a range while
2109 * deleting cols. Otherwise we #REF! before we can shorten.
2110 * The -1 is safe, origin.start.col == 0 is handled above */
2111 if (rinfo
->reloc_type
== GNM_EXPR_RELOCATE_COLS
&&
2112 rinfo
->col_offset
>= gnm_sheet_get_max_cols (end_sheet
))
2113 rng
->end
.col
= rinfo
->origin
.start
.col
- 1;
2115 rng
->end
.col
+= rinfo
->col_offset
;
2124 reloc_normalize_cellref (RelocInfoInternal
const *rinfo
, GnmCellRef
const *ref
,
2125 Sheet
**sheet
, GnmCellPos
*res
)
2127 *sheet
= eval_sheet (ref
->sheet
, rinfo
->details
->pos
.sheet
);
2128 res
->col
= ref
->col
;
2129 if (ref
->col_relative
) {
2130 if (rinfo
->check_rels
)
2131 res
->col
+= rinfo
->details
->pos
.eval
.col
;
2135 res
->row
= ref
->row
;
2136 if (ref
->row_relative
) {
2137 if (rinfo
->check_rels
)
2138 res
->row
+= rinfo
->details
->pos
.eval
.row
;
2144 /* Return %TRUE if @pos is out of bounds */
2146 reloc_restore_cellref (RelocInfoInternal
const *rinfo
,
2147 GnmSheetSize
const *ss
, GnmCellPos
const *pos
,
2150 if (res
->sheet
== rinfo
->details
->origin_sheet
) {
2151 res
->sheet
= rinfo
->details
->target_sheet
;
2153 ss
= gnm_sheet_get_size (res
->sheet
);
2156 if (!res
->col_relative
|| rinfo
->check_rels
) {
2157 if (pos
->col
< 0 || ss
->max_cols
<= pos
->col
)
2159 res
->col
= pos
->col
;
2160 if (res
->col_relative
) {
2161 res
->col
-= rinfo
->details
->pos
.eval
.col
;
2162 if (rinfo
->from_inside
)
2163 res
->col
-= rinfo
->details
->col_offset
;
2167 if (!res
->row_relative
|| rinfo
->check_rels
) {
2168 if (pos
->row
< 0 || ss
->max_rows
<= pos
->row
)
2170 res
->row
= pos
->row
;
2171 if (res
->row_relative
) {
2172 res
->row
-= rinfo
->details
->pos
.eval
.row
;
2173 if (rinfo
->from_inside
)
2174 res
->row
-= rinfo
->details
->row_offset
;
2182 static GnmExpr
const *
2183 reloc_cellrange (RelocInfoInternal
const *rinfo
, GnmValueRange
const *v
,
2184 gboolean sticky_end
)
2187 Sheet
*start_sheet
, *end_sheet
;
2188 GnmSheetSize
const *start_ss
, *end_ss
;
2189 gboolean full_col
, full_row
;
2190 gboolean full_col_begin
, full_row_begin
;
2192 /* Normalize the rangeRef, and remember if we had a full col/row
2193 * ref. If relocating the result changes things, or if we're from
2194 * inside the range that is moving map back to a RangeRef from the
2195 * target position. If the result is different that the original
2196 * generate a new expression. */
2197 reloc_normalize_cellref (rinfo
, &v
->cell
.a
, &start_sheet
, &r
.start
);
2198 reloc_normalize_cellref (rinfo
, &v
->cell
.b
, &end_sheet
, &r
.end
);
2199 /* (Foo,NULL) in Bar will generate (Foo,Bar) in normalize */
2200 if (NULL
== v
->cell
.b
.sheet
)
2201 end_sheet
= start_sheet
;
2202 start_ss
= gnm_sheet_get_size2 (start_sheet
, rinfo
->details
->pos
.wb
);
2203 end_ss
= gnm_sheet_get_size2 (end_sheet
, rinfo
->details
->pos
.wb
);
2205 full_col
= sticky_end
&& r
.end
.row
>= start_ss
->max_rows
- 1;
2206 full_col_begin
= full_col
&& r
.start
.row
== 0;
2208 full_row
= sticky_end
&& r
.end
.col
>= start_ss
->max_cols
- 1;
2209 full_row_begin
= full_row
&& r
.start
.col
== 0;
2211 if (reloc_range (rinfo
->details
, start_sheet
, end_sheet
, &r
) ||
2212 rinfo
->from_inside
) {
2213 GnmRangeRef res
= v
->cell
;
2216 r
.end
.row
= start_ss
->max_rows
- 1;
2220 r
.end
.col
= start_ss
->max_cols
- 1;
2224 if (reloc_restore_cellref (rinfo
, start_ss
, &r
.start
, &res
.a
) ||
2225 reloc_restore_cellref (rinfo
, end_ss
, &r
.end
, &res
.b
))
2226 return gnm_expr_new_constant (value_new_error_REF (NULL
));
2227 if (gnm_rangeref_equal (&res
, &v
->cell
))
2229 return gnm_expr_new_constant (value_new_cellrange_unsafe (&res
.a
, &res
.b
));
2235 static GnmExpr
const *
2236 gnm_expr_relocate (GnmExpr
const *expr
, RelocInfoInternal
const *rinfo
);
2238 static GnmExpr
const *
2239 cb_relocate (GnmExpr
const *expr
, GnmExprWalk
*data
)
2241 RelocInfoInternal
const *rinfo
= data
->user
;
2243 switch (GNM_EXPR_GET_OPER (expr
)) {
2244 case GNM_EXPR_OP_NAME
: {
2245 GnmNamedExpr
*nexpr
= expr
->name
.name
;
2247 /* we cannot invalidate references to the name that are
2248 * sitting in the undo queue, or the clipboard. So we just
2249 * flag the name as inactive and remove the reference here.
2251 if (!expr_name_is_active (nexpr
))
2252 return gnm_expr_new_constant (value_new_error_REF (NULL
));
2254 switch (rinfo
->details
->reloc_type
) {
2255 case GNM_EXPR_RELOCATE_INVALIDATE_SHEET
:
2256 if (nexpr
->pos
.sheet
&& nexpr
->pos
.sheet
->being_invalidated
)
2257 return gnm_expr_new_constant (value_new_error_REF (NULL
));
2261 case GNM_EXPR_RELOCATE_MOVE_RANGE
:
2263 * If the name is not officially scoped, check
2264 * that it is available in the new scope
2266 if (expr
->name
.optional_scope
== NULL
&&
2267 rinfo
->details
->target_sheet
!= rinfo
->details
->origin_sheet
) {
2268 GnmNamedExpr
*new_nexpr
;
2270 parse_pos_init_sheet (&pos
, rinfo
->details
->target_sheet
);
2272 /* If the name is not available in the new scope explicitly scope it */
2273 new_nexpr
= expr_name_lookup (&pos
, expr_name_name (nexpr
));
2274 if (new_nexpr
== NULL
) {
2275 if (nexpr
->pos
.sheet
!= NULL
)
2276 return gnm_expr_new_name (nexpr
, nexpr
->pos
.sheet
, NULL
);
2277 return gnm_expr_new_name (nexpr
, NULL
, nexpr
->pos
.wb
);
2280 /* replace it with the new name using qualified as
2281 * local to the target sheet
2283 return gnm_expr_new_name (new_nexpr
, pos
.sheet
, NULL
);
2286 * Do NOT rewrite the name.
2288 * Just invalidate the use of the name if the
2289 * name's expression, if relocated, would
2292 GnmExpr
const *tmp
=
2293 gnm_expr_relocate (nexpr
->texpr
->expr
,
2295 if (tmp
&& gnm_expr_is_err (tmp
, GNM_ERROR_REF
))
2299 gnm_expr_free (tmp
);
2304 case GNM_EXPR_RELOCATE_COLS
:
2305 case GNM_EXPR_RELOCATE_ROWS
:
2309 g_assert_not_reached ();
2313 case GNM_EXPR_OP_CELLREF
: {
2314 GnmCellRef
const *ref
= &expr
->cellref
.ref
;
2315 switch (rinfo
->details
->reloc_type
) {
2316 case GNM_EXPR_RELOCATE_INVALIDATE_SHEET
:
2318 ref
->sheet
->being_invalidated
)
2319 return gnm_expr_new_constant (value_new_error_REF (NULL
));
2322 case GNM_EXPR_RELOCATE_MOVE_RANGE
:
2323 case GNM_EXPR_RELOCATE_COLS
:
2324 case GNM_EXPR_RELOCATE_ROWS
: {
2327 GnmSheetSize
const *ss
;
2329 reloc_normalize_cellref (rinfo
, ref
, &sheet
, &r
.start
);
2331 ss
= gnm_sheet_get_size2 (sheet
, rinfo
->details
->pos
.wb
);
2333 if (reloc_range (rinfo
->details
, sheet
, sheet
, &r
) ||
2334 rinfo
->from_inside
) {
2335 GnmCellRef res
= *ref
;
2336 if (reloc_restore_cellref (rinfo
, ss
, &r
.start
, &res
))
2337 return gnm_expr_new_constant (value_new_error_REF (NULL
));
2338 if (gnm_cellref_equal (&res
, ref
))
2340 return gnm_expr_new_cellref (&res
);
2346 g_assert_not_reached ();
2352 case GNM_EXPR_OP_CONSTANT
:
2353 if (VALUE_IS_CELLRANGE (expr
->constant
.value
)) {
2354 GnmValueRange
const *vr
= &expr
->constant
.value
->v_range
;
2355 switch (rinfo
->details
->reloc_type
) {
2356 case GNM_EXPR_RELOCATE_INVALIDATE_SHEET
:
2357 return invalidate_sheet_cellrange (rinfo
, vr
);
2358 case GNM_EXPR_RELOCATE_MOVE_RANGE
:
2359 return reloc_cellrange (rinfo
, vr
, TRUE
);
2360 case GNM_EXPR_RELOCATE_COLS
:
2361 case GNM_EXPR_RELOCATE_ROWS
:
2362 return reloc_cellrange (rinfo
, vr
, rinfo
->details
->sticky_end
);
2364 g_assert_not_reached ();
2374 static GnmExpr
const *
2375 gnm_expr_relocate (GnmExpr
const *expr
, RelocInfoInternal
const *rinfo
)
2377 g_return_val_if_fail (expr
!= NULL
, NULL
);
2378 return gnm_expr_walk (expr
, cb_relocate
, (gpointer
)rinfo
);
2382 * gnm_expr_get_func_def:
2383 * @expr: Function call expressions
2385 * Returns: (transfer none): the called function.
2388 gnm_expr_get_func_def (GnmExpr
const *expr
)
2390 g_return_val_if_fail (expr
!= NULL
, NULL
);
2391 g_return_val_if_fail (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_FUNCALL
, NULL
);
2393 return expr
->func
.func
;
2397 * gnm_expr_get_func_arg:
2398 * @expr: Function call expressions
2399 * @i: argument index
2401 * Returns: (transfer none): the @i'th argument of the function call @expr.
2404 gnm_expr_get_func_arg (GnmExpr
const *expr
, int i
)
2406 g_return_val_if_fail (expr
!= NULL
, NULL
);
2407 g_return_val_if_fail (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_FUNCALL
, NULL
);
2408 g_return_val_if_fail (i
>= 0 && i
< expr
->func
.argc
, NULL
);
2410 return expr
->func
.argv
[i
];
2415 cellref_boundingbox (GnmCellRef
const *cr
, Sheet
const *sheet
, GnmRange
*bound
)
2417 GnmSheetSize
const *ss
;
2421 ss
= gnm_sheet_get_size (sheet
);
2423 if (cr
->col_relative
) {
2425 int const c
= ss
->max_cols
- cr
->col
- 1;
2426 if (bound
->end
.col
> c
)
2429 int const c
= -cr
->col
;
2430 if (bound
->start
.col
< c
)
2431 bound
->start
.col
= c
;
2434 if (cr
->row_relative
) {
2436 int const r
= ss
->max_rows
- cr
->row
- 1;
2437 if (bound
->end
.row
> r
)
2440 int const r
= -cr
->row
;
2441 if (bound
->start
.row
< r
)
2442 bound
->start
.row
= r
;
2447 static GnmExpr
const *
2448 cb_contains_subtotal (GnmExpr
const *expr
, GnmExprWalk
*data
)
2450 gboolean
*res
= data
->user
;
2451 if (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_FUNCALL
&&
2452 strcmp (expr
->func
.func
->name
, "subtotal") == 0) {
2460 * gnm_expr_containts_subtotal:
2463 * Returns: %TRUE if the expression calls the SUBTOTAL function
2466 gnm_expr_contains_subtotal (GnmExpr
const *expr
)
2468 gboolean res
= FALSE
;
2469 gnm_expr_walk (expr
, cb_contains_subtotal
, &res
);
2474 * gnm_expr_get_range:
2477 * Returns: (transfer full) (nullable): If this expression contains a
2478 * single range, return it. Otherwise, %NULL. A cell reference is
2479 * returned as a singleton range.
2482 gnm_expr_get_range (GnmExpr
const *expr
)
2484 g_return_val_if_fail (expr
!= NULL
, NULL
);
2486 switch (GNM_EXPR_GET_OPER (expr
)) {
2487 case GNM_EXPR_OP_CELLREF
:
2488 return value_new_cellrange_unsafe (
2489 &expr
->cellref
.ref
, &expr
->cellref
.ref
);
2491 case GNM_EXPR_OP_CONSTANT
:
2492 if (VALUE_IS_CELLRANGE (expr
->constant
.value
))
2493 return value_dup (expr
->constant
.value
);
2496 case GNM_EXPR_OP_NAME
:
2497 if (!expr_name_is_active (expr
->name
.name
))
2499 return gnm_expr_top_get_range (expr
->name
.name
->texpr
);
2501 case GNM_EXPR_OP_PAREN
:
2502 return gnm_expr_get_range (expr
->unary
.value
);
2510 gnm_insert_unique_value_cmp (gconstpointer a
, gconstpointer b
)
2512 return (value_equal (a
,b
) ? 0 : 1);
2518 gnm_insert_unique_value (GSList
*list
, GnmValue
*data
)
2520 if (g_slist_find_custom (list
, data
,
2521 gnm_insert_unique_value_cmp
)
2523 return g_slist_prepend (list
, data
);
2524 value_release (data
);
2529 * gnm_expr_is_rangeref:
2532 * Returns: %TRUE if the expression can generate a reference.
2533 * NOTE: in the future it would be nice to know if a function
2534 * can return a reference to tighten that up a bit.
2537 gnm_expr_is_rangeref (GnmExpr
const *expr
)
2539 g_return_val_if_fail (expr
!= NULL
, FALSE
);
2541 switch (GNM_EXPR_GET_OPER (expr
)) {
2542 /* would be better if we could differential which functions can return refs */
2543 case GNM_EXPR_OP_FUNCALL
:
2545 /* a set in a set, do we need this ? */
2546 case GNM_EXPR_OP_SET
:
2548 case GNM_EXPR_OP_RANGE_CTOR
:
2549 case GNM_EXPR_OP_INTERSECT
:
2550 case GNM_EXPR_OP_CELLREF
:
2553 case GNM_EXPR_OP_CONSTANT
:
2554 if (VALUE_IS_CELLRANGE (expr
->constant
.value
))
2558 case GNM_EXPR_OP_NAME
:
2559 if (expr_name_is_active (expr
->name
.name
))
2560 return gnm_expr_is_rangeref (expr
->name
.name
->texpr
->expr
);
2563 case GNM_EXPR_OP_ARRAY_CORNER
: /* I don't think this is possible */
2564 case GNM_EXPR_OP_ARRAY_ELEM
:
2571 gnm_expr_is_data_table (GnmExpr
const *expr
, GnmCellPos
*c_in
, GnmCellPos
*r_in
)
2573 if (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_FUNCALL
) {
2574 char const *name
= gnm_func_get_name (expr
->func
.func
, FALSE
);
2575 if (name
&& 0 == strcmp (name
, "table")) {
2577 GnmExpr
const *r
= (expr
->func
.argc
<= 0)
2579 : expr
->func
.argv
[0];
2581 if (r
!= NULL
&& GNM_EXPR_GET_OPER (r
) == GNM_EXPR_OP_CELLREF
) {
2582 r_in
->col
= r
->cellref
.ref
.col
;
2583 r_in
->row
= r
->cellref
.ref
.row
;
2585 r_in
->col
= r_in
->row
= 0; /* impossible */
2588 GnmExpr
const *c
= (expr
->func
.argc
<= 1)
2590 : expr
->func
.argv
[1];
2592 if (c
!= NULL
&& GNM_EXPR_GET_OPER (c
) == GNM_EXPR_OP_CELLREF
) {
2593 c_in
->col
= c
->cellref
.ref
.col
;
2594 c_in
->row
= c
->cellref
.ref
.row
;
2596 c_in
->col
= c_in
->row
= 0; /* impossible */
2602 /* Do we need anything else here ? */
2607 static GnmExpr
const *
2608 do_expr_walk (GnmExpr
const *expr
, GnmExprWalkerFunc walker
, GnmExprWalk
*data
)
2612 res
= walker (expr
, data
);
2614 if (res
) gnm_expr_free (res
);
2620 switch (GNM_EXPR_GET_OPER (expr
)) {
2621 case GNM_EXPR_OP_RANGE_CTOR
:
2622 case GNM_EXPR_OP_INTERSECT
:
2623 case GNM_EXPR_OP_ANY_BINARY
: {
2624 GnmExpr
const *a
, *b
;
2626 a
= do_expr_walk (expr
->binary
.value_a
, walker
, data
);
2630 b
= do_expr_walk (expr
->binary
.value_b
, walker
, data
);
2632 if (a
) gnm_expr_free (a
);
2640 a
= gnm_expr_copy (expr
->binary
.value_a
);
2642 b
= gnm_expr_copy (expr
->binary
.value_b
);
2644 return gnm_expr_new_binary (a
, GNM_EXPR_GET_OPER (expr
), b
);
2647 case GNM_EXPR_OP_ANY_UNARY
: {
2648 GnmExpr
const *a
= do_expr_walk (expr
->unary
.value
, walker
, data
);
2650 ? gnm_expr_new_unary (GNM_EXPR_GET_OPER (expr
), a
)
2654 case GNM_EXPR_OP_FUNCALL
: {
2655 gboolean any
= FALSE
;
2657 int argc
= expr
->func
.argc
;
2658 GnmExprConstPtr
*argv
=
2659 argc
? g_new (GnmExprConstPtr
, argc
) : NULL
;
2661 for (i
= 0; i
< argc
; i
++) {
2662 argv
[i
] = do_expr_walk (expr
->func
.argv
[i
], walker
, data
);
2666 gnm_expr_free (argv
[i
]);
2676 for (i
= 0; i
< argc
; i
++)
2678 argv
[i
] = gnm_expr_copy (expr
->func
.argv
[i
]);
2679 return gnm_expr_new_funcallv (expr
->func
.func
,
2686 case GNM_EXPR_OP_SET
: {
2687 gboolean any
= FALSE
;
2689 int argc
= expr
->set
.argc
;
2690 GnmExprConstPtr
*argv
=
2691 argc
? g_new (GnmExprConstPtr
, argc
) : NULL
;
2693 for (i
= 0; i
< argc
; i
++) {
2694 argv
[i
] = do_expr_walk (expr
->set
.argv
[i
], walker
, data
);
2698 gnm_expr_free (argv
[i
]);
2708 for (i
= 0; i
< argc
; i
++)
2710 argv
[i
] = gnm_expr_copy (expr
->set
.argv
[i
]);
2711 return gnm_expr_new_setv (argc
, argv
);
2718 case GNM_EXPR_OP_ARRAY_CORNER
: {
2719 GnmExpr
const *e
= do_expr_walk (expr
->array_corner
.expr
, walker
, data
);
2721 ? gnm_expr_new_array_corner (
2722 expr
->array_corner
.cols
,
2723 expr
->array_corner
.rows
, e
)
2734 * @expr: expression to walk
2735 * @walker: (scope call): callback for each sub-expression
2736 * @user: user data pointer
2738 * Returns: (transfer full) (allow-none): transformed expression.
2740 * This function walks the expression and calls the walker function for
2741 * each subexpression. If the walker returns a non-%NULL expression,
2742 * a new expression is built.
2744 * The walker will be called for an expression before its subexpressions.
2745 * It will receive the expression as its first argument and a GnmExprWalk
2746 * pointer as its second. It may set the stop flag to terminate the walk
2747 * in which case gnm_expr_walk will return %NULL.
2750 gnm_expr_walk (GnmExpr
const *expr
, GnmExprWalkerFunc walker
, gpointer user
)
2754 g_return_val_if_fail (expr
!= NULL
, NULL
);
2759 return do_expr_walk (expr
, walker
, &data
);
2763 * gnm_expr_is_empty:
2766 * Returns: %TRUE if @expr is a constant expression with the empty value.
2769 gnm_expr_is_empty (GnmExpr
const *expr
)
2771 g_return_val_if_fail (expr
!= NULL
, FALSE
);
2773 return (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_CONSTANT
&&
2774 VALUE_IS_EMPTY (expr
->constant
.value
));
2778 * gnm_expr_list_unref:
2779 * @list: (transfer full): expression list
2781 * This frees list and all the expressions in it.
2784 gnm_expr_list_unref (GnmExprList
*list
)
2787 for (l
= list
; l
; l
= l
->next
)
2788 gnm_expr_free (l
->data
);
2789 gnm_expr_list_free (list
);
2793 * gnm_expr_list_copy:
2794 * @list: (transfer none): list of expressions
2796 * Returns: (transfer full): a copy of the list and all the
2797 * expressions in it.
2800 gnm_expr_list_copy (GnmExprList
*list
)
2802 GnmExprList
*res
= g_slist_copy (list
); /* shallow */
2805 for (l
= res
; l
; l
= l
->next
)
2806 l
->data
= (GnmExpr
*) gnm_expr_copy (l
->data
);
2813 gnm_expr_list_as_string (int argc
,
2814 GnmExprConstPtr
const *argv
,
2815 GnmConventionsOut
*out
)
2819 if (out
->convs
->arg_sep
)
2820 arg_sep
= out
->convs
->arg_sep
;
2822 arg_sep
= go_locale_get_arg_sep ();
2824 g_string_append_c (out
->accum
, '(');
2825 for (i
= 0; i
< argc
; i
++) {
2827 g_string_append_unichar (out
->accum
, arg_sep
);
2828 do_expr_as_string (argv
[i
], 0, out
);
2830 g_string_append_c (out
->accum
, ')');
2834 gnm_expr_hash (GnmExpr
const *expr
)
2836 guint h
= (guint
)(GNM_EXPR_GET_OPER (expr
));
2838 switch (GNM_EXPR_GET_OPER (expr
)){
2839 case GNM_EXPR_OP_INTERSECT
:
2840 case GNM_EXPR_OP_RANGE_CTOR
:
2841 case GNM_EXPR_OP_ANY_BINARY
:
2842 return ((gnm_expr_hash (expr
->binary
.value_a
) * 7) ^
2843 (gnm_expr_hash (expr
->binary
.value_b
) * 3) ^
2846 case GNM_EXPR_OP_ANY_UNARY
:
2847 return ((gnm_expr_hash (expr
->unary
.value
) * 7) ^
2850 case GNM_EXPR_OP_FUNCALL
: {
2852 for (i
= 0; i
< expr
->func
.argc
; i
++)
2853 h
= (h
* 3) ^ gnm_expr_hash (expr
->func
.argv
[i
]);
2857 case GNM_EXPR_OP_SET
: {
2859 for (i
= 0; i
< expr
->set
.argc
; i
++)
2860 h
= (h
* 3) ^ gnm_expr_hash (expr
->set
.argv
[i
]);
2864 case GNM_EXPR_OP_CONSTANT
:
2865 return value_hash (expr
->constant
.value
);
2867 case GNM_EXPR_OP_NAME
:
2868 /* all we need is a somewhat unique hash, ignore int != ptr */
2869 return GPOINTER_TO_UINT (expr
->name
.name
);
2871 case GNM_EXPR_OP_CELLREF
:
2872 return gnm_cellref_hash (&expr
->cellref
.ref
);
2874 case GNM_EXPR_OP_ARRAY_CORNER
:
2875 return gnm_expr_hash (expr
->array_corner
.expr
);
2877 case GNM_EXPR_OP_ARRAY_ELEM
:
2878 return ((expr
->array_elem
.x
<< 16) ^
2879 (expr
->array_elem
.y
));
2886 /***************************************************************************/
2889 gnm_expr_sharer_new (void)
2891 GnmExprSharer
*es
= g_new (GnmExprSharer
, 1);
2893 es
->nodes_stored
= 0;
2894 es
->nodes_killed
= 0;
2895 es
->exprs
= g_hash_table_new_full
2896 ((GHashFunc
)gnm_expr_top_hash
,
2897 (GEqualFunc
)gnm_expr_top_equal
,
2898 (GDestroyNotify
)gnm_expr_top_unref
,
2905 gnm_expr_sharer_destroy (GnmExprSharer
*es
)
2907 if (!es
|| es
->ref_count
-- > 1)
2909 g_hash_table_destroy (es
->exprs
);
2913 static GnmExprSharer
*
2914 gnm_expr_sharer_ref (GnmExprSharer
*es
)
2921 gnm_expr_sharer_get_type (void)
2926 t
= g_boxed_type_register_static ("GnmExprSharer",
2927 (GBoxedCopyFunc
)gnm_expr_sharer_ref
,
2928 (GBoxedFreeFunc
)gnm_expr_sharer_destroy
);
2934 gnm_expr_sharer_share (GnmExprSharer
*es
, GnmExprTop
const *texpr
)
2936 GnmExprTop
const *shared
;
2938 g_return_val_if_fail (es
!= NULL
, texpr
);
2939 g_return_val_if_fail (texpr
!= NULL
, NULL
);
2943 /* Corners must not get shared. */
2944 if (GNM_EXPR_GET_OPER (texpr
->expr
) == GNM_EXPR_OP_ARRAY_CORNER
)
2947 shared
= g_hash_table_lookup (es
->exprs
, texpr
);
2949 gnm_expr_top_ref (shared
);
2950 if (texpr
->refcount
== 1)
2952 gnm_expr_top_unref (texpr
);
2956 gnm_expr_top_ref (texpr
);
2957 g_hash_table_insert (es
->exprs
, (gpointer
)texpr
, (gpointer
)texpr
);
2964 gnm_expr_sharer_report (GnmExprSharer
*es
)
2966 g_printerr ("Expressions in: %d\n", es
->nodes_in
);
2967 g_printerr ("Expressions stored: %d\n", es
->nodes_stored
);
2968 g_printerr ("Expressions killed: %d\n", es
->nodes_killed
);
2971 /***************************************************************************/
2974 gnm_expr_top_new (GnmExpr
const *expr
)
2981 res
= g_new (GnmExprTop
, 1);
2982 res
->magic
= GNM_EXPR_TOP_MAGIC
;
2990 gnm_expr_top_new_constant (GnmValue
*v
)
2992 return gnm_expr_top_new (gnm_expr_new_constant (v
));
2996 gnm_expr_top_ref (GnmExprTop
const *texpr
)
2998 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
2999 ((GnmExprTop
*)texpr
)->refcount
++;
3004 gnm_expr_top_unref (GnmExprTop
const *texpr
)
3006 g_return_if_fail (GNM_IS_EXPR_TOP (texpr
));
3008 ((GnmExprTop
*)texpr
)->refcount
--;
3009 if (texpr
->refcount
== 0) {
3010 gnm_expr_free (texpr
->expr
);
3011 ((GnmExprTop
*)texpr
)->magic
= 0;
3012 g_free ((GnmExprTop
*)texpr
);
3017 gnm_expr_top_get_type (void)
3022 t
= g_boxed_type_register_static ("GnmExprTop",
3023 (GBoxedCopyFunc
)gnm_expr_top_ref
,
3024 (GBoxedFreeFunc
)gnm_expr_top_unref
);
3030 gnm_expr_top_is_shared (GnmExprTop
const *texpr
)
3032 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), FALSE
);
3034 return texpr
->refcount
> 1;
3038 gnm_expr_top_new_array_corner (int cols
, int rows
, GnmExpr
const *expr
)
3040 return gnm_expr_top_new (gnm_expr_new_array_corner (cols
, rows
, expr
));
3044 gnm_expr_top_new_array_elem (int x
, int y
)
3046 return gnm_expr_top_new (gnm_expr_new_array_elem (x
, y
));
3049 static GnmExpr
const *
3050 cb_get_ranges (GnmExpr
const *expr
, GnmExprWalk
*data
)
3052 GSList
**pranges
= data
->user
;
3054 /* There's no real reason to exclude names here, except that
3055 we used to do so. */
3056 if (GNM_EXPR_GET_OPER (expr
) != GNM_EXPR_OP_NAME
) {
3057 GnmValue
*v
= gnm_expr_get_range (expr
);
3059 *pranges
= gnm_insert_unique_value (*pranges
, v
);
3066 * gnm_expr_top_get_ranges:
3069 * A collect the set of GnmRanges in @expr.
3070 * Returns: (element-type GnmRange) (transfer full): a list of the unique
3071 * references Caller is responsible for releasing the list and the content.
3074 gnm_expr_top_get_ranges (GnmExprTop
const *texpr
)
3078 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
3079 gnm_expr_walk (texpr
->expr
, cb_get_ranges
, &res
);
3084 gnm_expr_top_get_range (GnmExprTop
const *texpr
)
3086 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
3088 return gnm_expr_get_range (texpr
->expr
);
3092 gnm_expr_top_as_string (GnmExprTop
const *texpr
,
3093 GnmParsePos
const *pp
,
3094 GnmConventions
const *convs
)
3096 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
3098 return gnm_expr_as_string (texpr
->expr
, pp
, convs
);
3102 gnm_expr_top_as_gstring (GnmExprTop
const *texpr
,
3103 GnmConventionsOut
*out
)
3105 g_return_if_fail (GNM_IS_EXPR_TOP (texpr
));
3106 g_return_if_fail (out
!= NULL
);
3108 do_expr_as_string (texpr
->expr
, 0, out
);
3112 gnm_expr_top_hash (GnmExprTop
const *texpr
)
3114 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), 0);
3116 if (texpr
->hash
== 0) {
3117 ((GnmExprTop
*)texpr
)->hash
= gnm_expr_hash (texpr
->expr
);
3118 /* The following line tests the truncated value. */
3119 if (texpr
->hash
== 0)
3120 ((GnmExprTop
*)texpr
)->hash
= 1;
3126 gnm_expr_top_equal (GnmExprTop
const *te1
, GnmExprTop
const *te2
)
3130 if (te1
== NULL
|| te2
== NULL
)
3133 g_return_val_if_fail (GNM_IS_EXPR_TOP (te1
), FALSE
);
3134 g_return_val_if_fail (GNM_IS_EXPR_TOP (te2
), FALSE
);
3136 if (te1
->hash
&& te2
->hash
&& te1
->hash
!= te2
->hash
)
3139 return gnm_expr_equal (te1
->expr
, te2
->expr
);
3143 * gnm_expr_top_relocate:
3144 * @texpr: #GnmExprTop to fixup
3145 * @rinfo: #GnmExprRelocateInfo details of relocation
3146 * @ignore_rel: Do not adjust relative refs (for internal use when
3147 * relocating named expressions. Most callers will want FALSE.
3149 * GNM_EXPR_RELOCATE_INVALIDATE_SHEET:
3150 * Convert any references to sheets marked being_invalidated into #REF!
3151 * GNM_EXPR_RELOCATE_MOVE_RANGE,
3152 * Find any references to the specified area and adjust them by the
3153 * supplied deltas. Check for out of bounds conditions. Return NULL if
3154 * no change is required.
3155 * If the expression is within the range to be moved, its relative
3156 * references to cells outside the range are adjusted to reference the
3157 * same cell after the move.
3158 * GNM_EXPR_RELOCATE_COLS
3159 * GNM_EXPR_RELOCATE_ROWS
3163 gnm_expr_top_relocate (GnmExprTop
const *texpr
,
3164 GnmExprRelocateInfo
const *rinfo
,
3165 gboolean ignore_rel
)
3167 RelocInfoInternal rinfo_tmp
;
3169 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
3170 g_return_val_if_fail (NULL
!= rinfo
, NULL
);
3172 rinfo_tmp
.details
= rinfo
;
3173 rinfo_tmp
.check_rels
= !ignore_rel
;
3174 if (rinfo
->reloc_type
!= GNM_EXPR_RELOCATE_INVALIDATE_SHEET
)
3175 rinfo_tmp
.from_inside
= (rinfo
->origin_sheet
== rinfo
->pos
.sheet
) &&
3176 range_contains (&rinfo
->origin
, rinfo
->pos
.eval
.col
, rinfo
->pos
.eval
.row
);
3178 return gnm_expr_top_new (gnm_expr_relocate (texpr
->expr
, &rinfo_tmp
));
3182 * Convenience function to change an expression from one sheet to another.
3185 gnm_expr_top_relocate_sheet (GnmExprTop
const *texpr
,
3189 GnmExprRelocateInfo rinfo
;
3190 GnmExprTop
const *res
;
3192 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
3193 g_return_val_if_fail (IS_SHEET (src
), NULL
);
3194 g_return_val_if_fail (IS_SHEET (dst
), NULL
);
3196 rinfo
.reloc_type
= GNM_EXPR_RELOCATE_MOVE_RANGE
;
3197 rinfo
.origin_sheet
= (Sheet
*)src
;
3198 rinfo
.target_sheet
= (Sheet
*)dst
;
3199 rinfo
.col_offset
= rinfo
.row_offset
= 0;
3200 range_init_full_sheet (&rinfo
.origin
, src
);
3201 /* Not sure what sheet to use, but it doesn't seem to matter. */
3202 parse_pos_init_sheet (&rinfo
.pos
, rinfo
.target_sheet
);
3204 res
= gnm_expr_top_relocate (texpr
, &rinfo
, FALSE
);
3206 if (gnm_expr_top_is_array_corner (texpr
))
3207 res
= gnm_expr_top_new (gnm_expr_copy (texpr
->expr
));
3209 gnm_expr_top_ref ((res
= texpr
));
3216 gnm_expr_top_contains_subtotal (GnmExprTop
const *texpr
)
3218 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), FALSE
);
3220 return gnm_expr_contains_subtotal (texpr
->expr
);
3223 static GnmExpr
const *
3224 cb_is_volatile (GnmExpr
const *expr
, GnmExprWalk
*data
)
3226 gboolean
*res
= data
->user
;
3227 if (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_FUNCALL
&&
3228 (gnm_func_get_flags (expr
->func
.func
) & GNM_FUNC_VOLATILE
)) {
3236 gnm_expr_top_is_volatile (GnmExprTop
const *texpr
)
3238 gboolean res
= FALSE
;
3241 * An expression is volatile if it contains a call to a volatile
3242 * function, even in cases like IF(TRUE,12,RAND()) where the
3243 * volatile function won't even be reached.
3246 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), FALSE
);
3247 gnm_expr_walk (texpr
->expr
, cb_is_volatile
, &res
);
3253 gnm_expr_top_eval_array_corner (GnmExprTop
const *texpr
,
3254 GnmEvalPos
const *pos
,
3255 GnmExprEvalFlags flags
)
3257 GnmExpr
const *expr
= texpr
->expr
;
3262 pos2
.array_texpr
= texpr
;
3263 a
= gnm_expr_eval (expr
->array_corner
.expr
, &pos2
,
3264 flags
| GNM_EXPR_EVAL_PERMIT_NON_SCALAR
);
3266 value_release (expr
->array_corner
.value
);
3268 /* Store real result (cast away const)*/
3269 ((GnmExpr
*)expr
)->array_corner
.value
= a
;
3272 (VALUE_IS_CELLRANGE (a
) || VALUE_IS_ARRAY (a
))) {
3273 if (value_area_get_width (a
, pos
) <= 0 ||
3274 value_area_get_height (a
, pos
) <= 0)
3275 return value_new_error_NA (pos
);
3276 a
= (GnmValue
*)value_area_get_x_y (a
, 0, 0, pos
);
3278 return handle_empty ((a
!= NULL
) ? value_dup (a
) : NULL
, flags
);
3282 gnm_expr_top_eval_array_elem (GnmExprTop
const *texpr
,
3283 GnmEvalPos
const *pos
,
3284 GnmExprEvalFlags flags
)
3286 GnmExpr
const *expr
= texpr
->expr
;
3287 /* The upper left corner manages the recalc of the expr */
3288 GnmCell
*corner
= array_elem_get_corner (&expr
->array_elem
,
3289 pos
->sheet
, &pos
->eval
);
3293 !gnm_expr_top_is_array_corner (corner
->base
.texpr
)) {
3294 g_warning ("Funky array setup.");
3295 return handle_empty (NULL
, flags
);
3298 gnm_cell_eval (corner
);
3299 a
= gnm_expr_top_get_array_value (corner
->base
.texpr
);
3301 return handle_empty (NULL
, flags
);
3303 if ((VALUE_IS_CELLRANGE (a
) || VALUE_IS_ARRAY (a
))) {
3304 int const num_x
= value_area_get_width (a
, pos
);
3305 int const num_y
= value_area_get_height (a
, pos
);
3306 int x
= expr
->array_elem
.x
;
3307 int y
= expr
->array_elem
.y
;
3309 /* Evaluate relative to the upper left corner */
3310 GnmEvalPos tmp_ep
= *pos
;
3311 tmp_ep
.eval
.col
-= x
;
3312 tmp_ep
.eval
.row
-= y
;
3314 /* If the src array is 1 element wide or tall we wrap */
3315 if (x
>= 1 && num_x
== 1)
3317 if (y
>= 1 && num_y
== 1)
3319 if (x
>= num_x
|| y
>= num_y
)
3320 return value_new_error_NA (pos
);
3322 a
= (GnmValue
*)value_area_get_x_y (a
, x
, y
, &tmp_ep
);
3325 return handle_empty ((a
!= NULL
) ? value_dup (a
) : NULL
, flags
);
3329 gnm_expr_top_eval (GnmExprTop
const *texpr
,
3330 GnmEvalPos
const *pos
,
3331 GnmExprEvalFlags flags
)
3335 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
3337 gnm_app_recalc_start ();
3339 if (gnm_expr_top_is_array_corner (texpr
))
3340 res
= gnm_expr_top_eval_array_corner (texpr
, pos
, flags
);
3341 else if (gnm_expr_top_is_array_elem (texpr
, NULL
, NULL
))
3342 res
= gnm_expr_top_eval_array_elem (texpr
, pos
, flags
);
3343 else if ((flags
& GNM_EXPR_EVAL_ARRAY_CONTEXT
) && !eval_pos_is_array_context (pos
)) {
3344 // Array context out of the blue. Fake it.
3346 GnmExprTop
const *fake
= gnm_expr_top_new_array_corner (1, 1, NULL
);
3347 ((GnmExpr
*)(fake
->expr
))->array_corner
.expr
= texpr
->expr
; // Patch in our expr
3349 pos2
.array_texpr
= fake
;
3350 res
= gnm_expr_eval (texpr
->expr
, &pos2
, flags
);
3351 ((GnmExpr
*)(fake
->expr
))->array_corner
.expr
= NULL
;
3352 gnm_expr_top_unref (fake
);
3354 res
= gnm_expr_eval (texpr
->expr
, pos
, flags
);
3355 gnm_app_recalc_finish ();
3361 gnm_insert_unique (GSList
*list
, gpointer data
)
3363 if (g_slist_find (list
, data
) == NULL
)
3364 return g_slist_prepend (list
, data
);
3368 static GnmExpr
const *
3369 cb_referenced_sheets (GnmExpr
const *expr
, GnmExprWalk
*data
)
3371 GSList
**psheets
= data
->user
;
3373 switch (GNM_EXPR_GET_OPER (expr
)) {
3374 case GNM_EXPR_OP_CELLREF
:
3375 *psheets
= gnm_insert_unique (*psheets
, expr
->cellref
.ref
.sheet
);
3378 case GNM_EXPR_OP_CONSTANT
: {
3379 GnmValue
const *v
= expr
->constant
.value
;
3380 if (!VALUE_IS_CELLRANGE (v
))
3382 *psheets
= gnm_insert_unique (*psheets
, v
->v_range
.cell
.a
.sheet
);
3383 /* A NULL b sheet means a's sheet. Do not insert that. */
3384 if (v
->v_range
.cell
.b
.sheet
)
3385 *psheets
= gnm_insert_unique (*psheets
, v
->v_range
.cell
.b
.sheet
);
3397 * gnm_expr_top_referenced_sheets:
3400 * Generates a list of the sheets referenced by the supplied expression.
3401 * Caller must free the list. Note, that NULL may occur in the result
3402 * if the expression has a range or cellref without a sheet.
3403 * Returns: (element-type Sheet) (transfer container): the created list.
3406 gnm_expr_top_referenced_sheets (GnmExprTop
const *texpr
)
3410 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
3411 gnm_expr_walk (texpr
->expr
, cb_referenced_sheets
, &res
);
3416 gnm_expr_top_is_err (GnmExprTop
const *texpr
, GnmStdError err
)
3418 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), FALSE
);
3419 return gnm_expr_is_err (texpr
->expr
, err
);
3423 * gnm_expr_top_get_constant:
3426 * If this expression consists of just a constant, return it.
3429 gnm_expr_top_get_constant (GnmExprTop
const *texpr
)
3431 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
3433 return gnm_expr_get_constant (texpr
->expr
);
3437 gnm_expr_top_get_cellref (GnmExprTop
const *texpr
)
3439 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
3440 return gnm_expr_get_cellref (texpr
->expr
);
3443 static GnmExpr
const *
3444 cb_first_funcall (GnmExpr
const *expr
, GnmExprWalk
*data
)
3446 GnmExprConstPtr
*user
= data
->user
;
3447 if (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_FUNCALL
) {
3455 * gnm_expr_top_first_funcall:
3460 gnm_expr_top_first_funcall (GnmExprTop
const *texpr
)
3462 GnmExpr
const *res
= NULL
;
3464 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
3465 gnm_expr_walk (texpr
->expr
, cb_first_funcall
, &res
);
3469 struct cb_get_boundingbox
{
3474 static GnmExpr
const *
3475 cb_get_boundingbox (GnmExpr
const *expr
, GnmExprWalk
*data
)
3477 struct cb_get_boundingbox
*args
= data
->user
;
3479 switch (GNM_EXPR_GET_OPER (expr
)) {
3480 case GNM_EXPR_OP_CELLREF
:
3481 cellref_boundingbox (&expr
->cellref
.ref
, args
->sheet
, args
->bound
);
3484 case GNM_EXPR_OP_CONSTANT
: {
3485 GnmValue
const *v
= expr
->constant
.value
;
3487 if (VALUE_IS_CELLRANGE (v
)) {
3488 cellref_boundingbox (&v
->v_range
.cell
.a
, args
->sheet
, args
->bound
);
3489 cellref_boundingbox (&v
->v_range
.cell
.b
, args
->sheet
, args
->bound
);
3502 * gnm_expr_top_get_boundingbox:
3504 * Returns the range of cells in which the expression can be used without going
3508 gnm_expr_top_get_boundingbox (GnmExprTop
const *texpr
, Sheet
const *sheet
,
3511 struct cb_get_boundingbox args
;
3513 g_return_if_fail (GNM_IS_EXPR_TOP (texpr
));
3515 range_init_full_sheet (bound
, sheet
);
3519 gnm_expr_walk (texpr
->expr
, cb_get_boundingbox
, &args
);
3523 gnm_expr_top_is_rangeref (GnmExprTop
const *texpr
)
3525 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), FALSE
);
3527 return gnm_expr_is_rangeref (texpr
->expr
);
3531 gnm_expr_top_is_array_corner (GnmExprTop
const *texpr
)
3533 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), FALSE
);
3534 return GNM_EXPR_GET_OPER (texpr
->expr
) == GNM_EXPR_OP_ARRAY_CORNER
;
3538 gnm_expr_top_get_array_size (GnmExprTop
const *texpr
, int *cols
, int *rows
)
3540 g_return_if_fail (GNM_IS_EXPR_TOP (texpr
));
3541 g_return_if_fail (GNM_EXPR_GET_OPER (texpr
->expr
) == GNM_EXPR_OP_ARRAY_CORNER
);
3544 *cols
= texpr
->expr
->array_corner
.cols
;
3546 *rows
= texpr
->expr
->array_corner
.rows
;
3550 gnm_expr_top_get_array_value (GnmExprTop
const *texpr
)
3552 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
3553 g_return_val_if_fail (GNM_EXPR_GET_OPER (texpr
->expr
) == GNM_EXPR_OP_ARRAY_CORNER
, NULL
);
3554 return texpr
->expr
->array_corner
.value
;
3558 gnm_expr_top_get_array_expr (GnmExprTop
const *texpr
)
3560 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
3561 g_return_val_if_fail (GNM_EXPR_GET_OPER (texpr
->expr
) == GNM_EXPR_OP_ARRAY_CORNER
, NULL
);
3562 return texpr
->expr
->array_corner
.expr
;
3566 gnm_expr_top_is_array_elem (GnmExprTop
const *texpr
, int *x
, int *y
)
3568 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), FALSE
);
3570 if (GNM_EXPR_GET_OPER (texpr
->expr
) != GNM_EXPR_OP_ARRAY_ELEM
)
3573 if (x
) *x
= texpr
->expr
->array_elem
.x
;
3574 if (y
) *y
= texpr
->expr
->array_elem
.y
;
3579 gnm_expr_top_is_array (GnmExprTop
const *texpr
)
3581 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), FALSE
);
3582 return gnm_expr_is_array (texpr
->expr
);
3586 gnm_expr_top_transpose (GnmExprTop
const *texpr
)
3588 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr
), NULL
);
3589 switch (GNM_EXPR_GET_OPER (texpr
->expr
)) {
3590 case GNM_EXPR_OP_ARRAY_CORNER
:
3591 /* Transpose size */
3592 return gnm_expr_top_new_array_corner
3593 (texpr
->expr
->array_corner
.rows
,
3594 texpr
->expr
->array_corner
.cols
,
3595 gnm_expr_copy (texpr
->expr
));
3596 case GNM_EXPR_OP_ARRAY_ELEM
:
3597 /* Transpose coordinates */
3598 return gnm_expr_top_new_array_elem
3599 (texpr
->expr
->array_elem
.y
,
3600 texpr
->expr
->array_elem
.x
);
3606 /****************************************************************************/
3610 guint32 oper_and_refcount
;
3611 GnmExprConstant constant
;
3612 GnmExprFunction func
;
3614 GnmExprBinary binary
;
3615 GnmExprArrayElem array_elem
;
3619 guint32 oper_and_refcount
;
3621 GnmExprCellRef cellref
;
3622 GnmExprArrayCorner array_corner
;
3627 * gnm_expr_init_: (skip)
3630 gnm_expr_init_ (void)
3636 /* 12 is an excellent size for a pool. */
3637 g_print ("sizeof(GnmExprSmall) = %d\n", (int)sizeof (GnmExprSmall
));
3638 g_print ("sizeof(GnmExprBig) = %d\n", (int)sizeof (GnmExprBig
));
3640 g_print ("sizeof(e.func) = %d\n", (int)sizeof (e
.func
));
3641 g_print ("sizeof(e.unary) = %d\n", (int)sizeof (e
.unary
));
3642 g_print ("sizeof(e.binary) = %d\n", (int)sizeof (e
.binary
));
3643 g_print ("sizeof(e.name) = %d\n", (int)sizeof (e
.name
));
3644 g_print ("sizeof(e.cellref) = %d\n", (int)sizeof (e
.cellref
));
3645 g_print ("sizeof(e.array_corner) = %d\n", (int)sizeof (e
.array_corner
));
3646 g_print ("sizeof(e.array_elem) = %d\n", (int)sizeof (e
.array_elem
));
3647 g_print ("sizeof(e.set) = %d\n", (int)sizeof (e
.set
));
3650 expression_pool_small
=
3651 go_mem_chunk_new ("expression pool for small nodes",
3652 sizeof (GnmExprSmall
),
3654 expression_pool_big
=
3655 go_mem_chunk_new ("expression pool for big nodes",
3656 sizeof (GnmExprBig
),
3663 cb_expression_pool_leak (gpointer data
, G_GNUC_UNUSED gpointer user
)
3665 GnmExpr
const *expr
= data
;
3673 s
= gnm_expr_as_string (expr
, &pp
, NULL
);
3674 g_printerr ("Leaking expression at %p: %s.\n", (void *)expr
, s
);
3680 * gnm_expr_shutdown_: (skip)
3683 gnm_expr_shutdown_ (void)
3686 go_mem_chunk_foreach_leak (expression_pool_small
, cb_expression_pool_leak
, NULL
);
3687 go_mem_chunk_destroy (expression_pool_small
, FALSE
);
3688 expression_pool_small
= NULL
;
3690 go_mem_chunk_foreach_leak (expression_pool_big
, cb_expression_pool_leak
, NULL
);
3691 go_mem_chunk_destroy (expression_pool_big
, FALSE
);
3692 expression_pool_big
= NULL
;
3696 /****************************************************************************/