Introspection: update bless api
[gnumeric.git] / src / expr.c
blobb40d7944a29a5851fd65fbbeed714c216e7d206d
1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
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
22 * USA
24 #include <gnumeric-config.h>
25 #include <glib/gi18n-lib.h>
26 #include "gnumeric.h"
27 #include "expr.h"
29 #include "expr-impl.h"
30 #include "expr-name.h"
31 #include "dependent.h"
32 #include "application.h"
33 #include "func.h"
34 #include "cell.h"
35 #include "sheet.h"
36 #include "value.h"
37 #include "parse-util.h"
38 #include "ranges.h"
39 #include "number-match.h"
40 #include "workbook.h"
41 #include "gutils.h"
42 #include "parse-util.h"
43 #include "mathfunc.h"
45 #include <goffice/goffice.h>
46 #include <math.h>
47 #include <string.h>
48 #include <stdlib.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
56 #endif
58 #if USE_EXPR_POOLS
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))
63 #else
64 #define CHUNK_ALLOC(T,c) g_new (T,1)
65 #define CHUNK_FREE(p,v) g_free ((v))
66 #endif
68 /***************************************************************************/
70 /**
71 * gnm_expr_new_constant :
72 * @v:
74 * Absorbs the value.
75 **/
76 GnmExpr const *
77 gnm_expr_new_constant (GnmValue *v)
79 GnmExprConstant *ans;
81 g_return_val_if_fail (v != NULL, NULL);
83 ans = CHUNK_ALLOC (GnmExprConstant, expression_pool_small);
84 if (!ans)
85 return NULL;
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)
96 GnmExprFunction *ans;
97 g_return_val_if_fail (func, NULL);
99 ans = CHUNK_ALLOC (GnmExprFunction, expression_pool_small);
101 ans->oper = GNM_EXPR_OP_FUNCALL;
102 gnm_func_ref (func);
103 ans->func = func;
104 ans->argc = argc;
105 ans->argv = argv;
107 return (GnmExpr *)ans;
110 GnmExpr const *
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;
116 int i;
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);
125 GnmExpr const *
126 gnm_expr_new_funcall1 (GnmFunc *func,
127 GnmExpr const *arg0)
129 GnmExprConstPtr *argv = g_new (GnmExprConstPtr, 1);
130 argv[0] = arg0;
131 return gnm_expr_new_funcallv (func, 1, argv);
134 GnmExpr const *
135 gnm_expr_new_funcall2 (GnmFunc *func,
136 GnmExpr const *arg0,
137 GnmExpr const *arg1)
139 GnmExprConstPtr *argv = g_new (GnmExprConstPtr, 2);
140 argv[0] = arg0;
141 argv[1] = arg1;
142 return gnm_expr_new_funcallv (func, 2, argv);
145 GnmExpr const *
146 gnm_expr_new_funcall3 (GnmFunc *func,
147 GnmExpr const *arg0,
148 GnmExpr const *arg1,
149 GnmExpr const *arg2)
151 GnmExprConstPtr *argv = g_new (GnmExprConstPtr, 3);
152 argv[0] = arg0;
153 argv[1] = arg1;
154 argv[2] = arg2;
155 return gnm_expr_new_funcallv (func, 3, argv);
158 GnmExpr const *
159 gnm_expr_new_funcall4 (GnmFunc *func,
160 GnmExpr const *arg0,
161 GnmExpr const *arg1,
162 GnmExpr const *arg2,
163 GnmExpr const *arg3)
165 GnmExprConstPtr *argv = g_new (GnmExprConstPtr, 4);
166 argv[0] = arg0;
167 argv[1] = arg1;
168 argv[2] = arg2;
169 argv[3] = arg3;
170 return gnm_expr_new_funcallv (func, 4, argv);
173 GnmExpr const *
174 gnm_expr_new_funcall5 (GnmFunc *func,
175 GnmExpr const *arg0,
176 GnmExpr const *arg1,
177 GnmExpr const *arg2,
178 GnmExpr const *arg3,
179 GnmExpr const *arg4)
181 GnmExprConstPtr *argv = g_new (GnmExprConstPtr, 5);
182 argv[0] = arg0;
183 argv[1] = arg1;
184 argv[2] = arg2;
185 argv[3] = arg3;
186 argv[4] = arg4;
187 return gnm_expr_new_funcallv (func, 5, argv);
191 /***************************************************************************/
193 GnmExpr const *
194 gnm_expr_new_unary (GnmExprOp op, GnmExpr const *e)
196 GnmExprUnary *ans;
198 ans = CHUNK_ALLOC (GnmExprUnary, expression_pool_small);
199 if (!ans)
200 return NULL;
202 ans->oper = op;
203 ans->value = e;
205 return (GnmExpr *)ans;
208 /***************************************************************************/
210 GnmExpr const *
211 gnm_expr_new_binary (GnmExpr const *l, GnmExprOp op, GnmExpr const *r)
213 GnmExprBinary *ans;
215 ans = CHUNK_ALLOC (GnmExprBinary, expression_pool_small);
216 if (!ans)
217 return NULL;
219 ans->oper = op;
220 ans->value_a = l;
221 ans->value_b = r;
223 return (GnmExpr *)ans;
226 /***************************************************************************/
228 GnmExpr const *
229 gnm_expr_new_name (GnmNamedExpr *name,
230 Sheet *optional_scope, Workbook *optional_wb_scope)
232 GnmExprName *ans;
234 ans = CHUNK_ALLOC (GnmExprName, expression_pool_big);
235 if (!ans)
236 return NULL;
238 ans->oper = GNM_EXPR_OP_NAME;
239 ans->name = 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 /***************************************************************************/
250 GnmExpr const *
251 gnm_expr_new_cellref (GnmCellRef const *cr)
253 GnmExprCellRef *ans;
255 ans = CHUNK_ALLOC (GnmExprCellRef, expression_pool_big);
256 if (!ans)
257 return NULL;
259 ans->oper = GNM_EXPR_OP_CELLREF;
260 ans->ref = *cr;
262 return (GnmExpr *)ans;
265 /***************************************************************************/
267 static gboolean
268 gnm_expr_is_array (GnmExpr const *expr)
270 return 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 :
277 * @cols:
278 * @rows:
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);
291 if (ans == NULL)
292 return NULL;
294 ans->oper = GNM_EXPR_OP_ARRAY_CORNER;
295 ans->rows = rows;
296 ans->cols = cols;
297 ans->value = NULL;
298 ans->expr = expr;
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);
308 if (ans == NULL)
309 return NULL;
311 ans->oper = GNM_EXPR_OP_ARRAY_ELEM;
312 ans->x = x;
313 ans->y = y;
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;
325 ans->argc = argc;
326 ans->argv = argv;
328 return (GnmExpr *)ans;
331 GnmExpr const *
332 gnm_expr_new_set (GnmExprList *set)
334 int i, argc;
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)
341 argv[i] = set->data;
342 gnm_expr_list_free (set0);
344 return gnm_expr_new_setv (argc, argv);
347 /***************************************************************************/
350 * gnm_expr_new_range_ctor:
351 * @l: start range
352 * @r: end range
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.
359 GnmExpr const *
360 gnm_expr_new_range_ctor (GnmExpr const *l, GnmExpr const *r)
362 GnmValue *v;
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)
368 goto fallback;
369 if (GNM_EXPR_GET_OPER (r) != GNM_EXPR_OP_CELLREF)
370 goto fallback;
372 v = value_new_cellrange_unsafe (&l->cellref.ref, &r->cellref.ref);
373 gnm_expr_free (l);
374 gnm_expr_free (r);
375 return gnm_expr_new_constant (v);
377 fallback:
378 return gnm_expr_new_binary (l, GNM_EXPR_OP_RANGE_CTOR, r);
381 /***************************************************************************/
383 GnmExpr const *
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);
405 int i;
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
411 (expr->func.func,
412 expr->func.argc,
413 argv);
416 case GNM_EXPR_OP_NAME:
417 return gnm_expr_new_name
418 (expr->name.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
436 (expr->array_elem.x,
437 expr->array_elem.y);
439 case GNM_EXPR_OP_SET: {
440 GnmExprConstPtr *argv =
441 g_new (GnmExprConstPtr, expr->set.argc);
442 int i;
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
448 (expr->set.argc,
449 argv);
452 #ifndef DEBUG_SWITCH_ENUM
453 default:
454 g_assert_not_reached ();
455 break;
456 #endif
461 * gnm_expr_free:
463 void
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);
475 break;
477 case GNM_EXPR_OP_FUNCALL: {
478 int i;
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);
485 break;
488 case GNM_EXPR_OP_NAME:
489 expr_name_unref (expr->name.name);
490 CHUNK_FREE (expression_pool_big, (gpointer)expr);
491 break;
493 case GNM_EXPR_OP_CONSTANT:
494 value_release ((GnmValue *)expr->constant.value);
495 CHUNK_FREE (expression_pool_small, (gpointer)expr);
496 break;
498 case GNM_EXPR_OP_CELLREF:
499 CHUNK_FREE (expression_pool_big, (gpointer)expr);
500 break;
502 case GNM_EXPR_OP_ANY_UNARY:
503 gnm_expr_free (expr->unary.value);
504 CHUNK_FREE (expression_pool_small, (gpointer)expr);
505 break;
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);
514 break;
516 case GNM_EXPR_OP_ARRAY_ELEM:
517 CHUNK_FREE (expression_pool_small, (gpointer)expr);
518 break;
520 case GNM_EXPR_OP_SET: {
521 int i;
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);
527 break;
530 #ifndef DEBUG_SWITCH_ENUM
531 default:
532 g_assert_not_reached ();
533 break;
534 #endif
538 GType
539 gnm_expr_get_type (void)
541 static GType t = 0;
543 if (t == 0) {
544 t = g_boxed_type_register_static ("GnmExpr",
545 (GBoxedCopyFunc)gnm_expr_copy,
546 (GBoxedFreeFunc)gnm_expr_free);
548 return t;
551 GType
552 gnm_expr_array_corner_get_type (void)
554 static GType t = 0;
556 if (t == 0) {
557 t = g_boxed_type_register_static ("GnmExprArrayCorner",
558 (GBoxedCopyFunc)gnm_expr_copy,
559 (GBoxedFreeFunc)gnm_expr_free);
561 return t;
565 * gnm_expr_equal:
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
570 * insufficeient.
572 gboolean
573 gnm_expr_equal (GnmExpr const *a, GnmExpr const *b)
575 if (a == b)
576 return TRUE;
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))
582 return FALSE;
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: {
595 int i;
597 if (a->func.func != b->func.func ||
598 a->func.argc != b->func.argc)
599 return FALSE;
601 for (i = 0; i < a->func.argc; i++)
602 if (!gnm_expr_equal (a->func.argv[i], b->func.argv[i]))
603 return FALSE;
604 return TRUE;
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: {
633 int i;
635 if (a->set.argc != b->set.argc)
636 return FALSE;
638 for (i = 0; i < a->set.argc; i++)
639 if (!gnm_expr_equal (a->set.argv[i], b->set.argv[i]))
640 return FALSE;
641 return TRUE;
645 return FALSE;
648 static GnmCell *
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);
661 return corner;
664 static gboolean
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;
671 GnmValue *v;
672 GnmFuncEvalInfo ei;
674 ei.pos = pos;
675 ei.func_call = &expr->func;
676 ei.flags = flags;
677 v = function_call_with_exprs (&ei);
679 if (v != NULL) {
680 if (VALUE_IS_CELLRANGE (v)) {
681 *res = v->v_range.cell;
682 failed = FALSE;
684 value_release (v);
686 return failed;
689 case GNM_EXPR_OP_CELLREF :
690 res->a = expr->cellref.ref;
691 res->b = expr->cellref.ref;
692 return FALSE;
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;
698 return FALSE;
700 return TRUE;
703 case GNM_EXPR_OP_NAME:
704 if (!expr_name_is_active (expr->name.name))
705 return TRUE;
706 return gnm_expr_extract_ref (res, expr->name.name->texpr->expr,
707 pos, flags);
708 default :
709 break;
711 return TRUE;
714 static inline GnmValue *
715 handle_empty (GnmValue *res, GnmExprEvalFlags flags)
717 if (res == NULL)
718 return (flags & GNM_EXPR_EVAL_PERMIT_EMPTY)
719 ? NULL : value_new_int (0);
721 if (VALUE_IS_EMPTY (res)) {
722 value_release (res);
723 return (flags & GNM_EXPR_EVAL_PERMIT_EMPTY)
724 ? NULL : value_new_int (0);
726 return res;
730 * value_intersection :
731 * @v: a VALUE_CELLRANGE or VALUE_ARRAY
732 * @pos:
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
738 * argument.
740 * Always release the value passed in.
742 * Return value:
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.
748 static GnmValue *
749 value_intersection (GnmValue *v, GnmEvalPos const *pos)
751 GnmValue *res = NULL;
752 GnmRange r;
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]);
760 value_release (v);
761 return res;
764 /* inverted ranges */
765 gnm_rangeref_normalize (&v->v_range.cell, pos, &start_sheet, &end_sheet, &r);
766 value_release (v);
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. */
774 col = r.start.col;
775 row = r.start.row;
776 found = TRUE;
777 } else if (r.start.row == r.end.row) {
778 if (r.start.col <= col && col <= r.end.col) {
779 row = r.start.row;
780 found = TRUE;
781 } else if (r.start.col == r.end.col) {
782 col = r.start.col;
783 row = r.start.row;
784 found = TRUE;
786 } else if (r.start.col == r.end.col) {
787 if (r.start.row <= row && row <= r.end.row) {
788 col = r.start.col;
789 found = TRUE;
792 if (found) {
793 GnmCell *cell = sheet_cell_get (
794 eval_sheet (start_sheet, pos->sheet),
795 col, row);
796 if (cell == NULL)
797 return value_new_empty ();
798 gnm_cell_eval (cell);
799 return value_dup (cell->value);
803 return value_new_error_VALUE (pos);
806 static GnmValue *
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);
812 gnm_float res;
814 switch (GNM_EXPR_GET_OPER (expr)) {
815 case GNM_EXPR_OP_ADD:
816 res = va + vb;
817 break;
819 case GNM_EXPR_OP_SUB:
820 res = va - vb;
821 break;
823 case GNM_EXPR_OP_MULT:
824 res = va * vb;
825 break;
827 case GNM_EXPR_OP_DIV:
828 if (vb == 0.0)
829 return value_new_error_DIV0 (ep);
830 res = va / vb;
831 break;
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);
838 break;
840 default:
841 g_assert_not_reached ();
844 if (gnm_finite (res))
845 return value_new_float (res);
846 else
847 return value_new_error_NUM (ep);
850 static GnmValue *
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);
866 switch (op) {
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
875 default:
876 g_assert_not_reached ();
877 #endif
879 return value_new_error (ep, _("Internal type error"));
882 static GnmValue *
883 cb_bin_cmp (GnmEvalPos const *ep, GnmValue const *a, GnmValue const *b,
884 GnmExpr const *expr)
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);
893 static GnmValue *
894 cb_bin_arith (GnmEvalPos const *ep, GnmValue const *a, GnmValue const *b,
895 GnmExpr const *expr)
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 workbook_date_conv (ep->sheet->workbook));
908 if (va == NULL)
909 return value_new_error_VALUE (ep);
910 } else if (!VALUE_IS_NUMBER (a))
911 return value_new_error_VALUE (ep);
912 else
913 va = (GnmValue *)a;
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 workbook_date_conv (ep->sheet->workbook));
919 if (vb == NULL) {
920 if (va != a)
921 value_release (va);
922 return value_new_error_VALUE (ep);
924 } else if (!VALUE_IS_NUMBER (b)) {
925 if (va != a)
926 value_release (va);
927 return value_new_error_VALUE (ep);
928 } else
929 vb = (GnmValue *)b;
931 res = bin_arith (expr, ep, va, vb);
932 if (va != a)
933 value_release (va);
934 if (vb != b)
935 value_release (vb);
936 return res;
939 static GnmValue *
940 cb_bin_cat (GnmEvalPos const *ep, GnmValue const *a, GnmValue const *b,
941 GnmExpr const *expr)
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);
947 if (a == NULL) {
948 if (b != NULL)
949 return value_new_string (value_peek_string (b));
950 else
951 return value_new_string ("");
952 } else if (b == NULL)
953 return value_new_string (value_peek_string (a));
954 else {
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,
962 GnmValue const *a,
963 GnmValue const *b,
964 gpointer user_data);
965 typedef struct {
966 GnmEvalPos const *ep;
967 GnmValue *res;
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
975 struct {
976 int a, b;
977 } x, y;
978 gpointer user_data;
979 } BinOpImplicitIteratorState;
981 static GnmValue *
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),
993 state->user_data);
994 return NULL;
996 static GnmValue *
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);
1003 return NULL;
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. */
1008 static GnmValue *
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 */
1017 iter_info.ep = ep;
1018 iter_info.func = func;
1019 iter_info.user_data = (gpointer) expr;
1020 iter_info.a = a;
1021 iter_info.b = b;
1023 /* matrix to matrix
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) */
1030 if (b != NULL &&
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))
1037 w = sa;
1038 if ((iter_info.x.b = (sb == 1) ? 0 : 1) && (w > sb || w == 1))
1039 w = sb;
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))
1044 h = sa;
1045 if ((iter_info.y.b = (sb == 1) ? 0 : 1) && (h > sb || h == 1))
1046 h = sb;
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);
1051 } else {
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);
1059 value_release (a);
1060 value_release (b);
1061 return iter_info.res;
1064 static GnmValue *
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);
1071 return NULL;
1073 static GnmValue *
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;
1083 iter_info.a = a;
1084 iter_info.b = b;
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);
1092 value_release (a);
1093 value_release (b);
1095 return iter_info.res;
1098 static GnmValue *
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));
1104 return tmp;
1105 } else
1106 return NULL;
1109 static GnmValue *
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 workbook_date_conv (v_iter->ep->sheet->workbook));
1123 if (conv != NULL) {
1124 tmp = negate_value (conv);
1125 value_release (conv);
1127 } else {
1128 /* BOOL goes here. */
1129 tmp = negate_value (v);
1132 if (NULL == tmp)
1133 tmp = value_new_error_VALUE (v_iter->ep);
1134 res->v_array.vals[v_iter->x][v_iter->y] = tmp;
1135 return NULL;
1138 static GnmValue *
1139 cb_iter_percentage (GnmValueIter const *v_iter, GnmValue *res)
1141 GnmValue const *v = v_iter->v;
1142 GnmValue *tmp;
1144 if (VALUE_IS_EMPTY (v))
1145 tmp = value_new_int (0);
1146 else if (VALUE_IS_ERROR (v))
1147 tmp = value_dup (v);
1148 else {
1149 GnmValue *conv = NULL;
1150 if (VALUE_IS_STRING (v)) {
1151 conv = format_match_number (
1152 value_peek_string (v), NULL,
1153 workbook_date_conv (v_iter->ep->sheet->workbook));
1154 if (conv != NULL)
1155 v = conv;
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 ());
1161 } else
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;
1168 return NULL;
1171 static GnmValue *
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);
1192 break;
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);
1204 break;
1205 default:
1206 g_assert_not_reached ();
1207 return NULL;
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);
1218 return res;
1222 * gnm_expr_eval :
1223 * @expr:
1224 * @pos:
1225 * @flags:
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.
1230 GnmValue *
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));
1239 retry:
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);
1251 if (a != NULL) {
1252 if (VALUE_IS_ERROR (a))
1253 return 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,
1258 expr);
1261 b = gnm_expr_eval (expr->binary.value_b, pos, flags);
1262 if (b != NULL) {
1263 if (VALUE_IS_ERROR (b)) {
1264 value_release (a);
1265 return 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,
1270 expr);
1273 res = bin_cmp (GNM_EXPR_GET_OPER (expr), value_compare (a, b, FALSE), pos);
1274 value_release (a);
1275 value_release (b);
1276 return res;
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:
1284 * Priority
1285 * 1) Error from A
1286 * 2) #!VALUE error if A is not a number
1287 * 3) Error from B
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 workbook_date_conv (pos->sheet->workbook));
1306 value_release (a);
1307 if (tmp == NULL)
1308 return value_new_error_VALUE (pos);
1309 a = tmp;
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 workbook_date_conv (pos->sheet->workbook));
1315 value_release (b);
1316 b = (res == NULL) ? value_new_error_VALUE (pos) : res;
1318 return bin_array_iter_a (pos, a, b,
1319 (BinOpImplicitIteratorFunc) cb_bin_arith,
1320 expr);
1321 } else if (!VALUE_IS_NUMBER (a)) {
1322 value_release (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)) {
1329 value_release (a);
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 workbook_date_conv (pos->sheet->workbook));
1338 value_release (b);
1339 if (tmp == NULL) {
1340 value_release (a);
1341 return value_new_error_VALUE (pos);
1343 b = tmp;
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,
1347 expr);
1348 else if (!VALUE_IS_NUMBER (b)) {
1349 value_release (a);
1350 value_release (b);
1351 return value_new_error_VALUE (pos);
1354 res = bin_arith (expr, pos, a, b);
1355 value_release (a);
1356 value_release (b);
1357 return res;
1359 case GNM_EXPR_OP_PAREN:
1360 /* Avoid recursive call to save stack. */
1361 expr = expr->unary.value;
1362 goto retry;
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))
1373 return a;
1374 if (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_UNARY_PLUS)
1375 return a;
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 workbook_date_conv (pos->sheet->workbook));
1382 value_release (a);
1383 if (tmp == NULL)
1384 return value_new_error_VALUE (pos);
1385 a = tmp;
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),
1393 res);
1394 value_release (a);
1395 return res;
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);
1401 else {
1402 res = value_new_float (value_get_as_float (a) / 100);
1403 value_set_fmt (res, go_format_default_percentage ());
1405 value_release (a);
1406 return res;
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);
1412 if (a != NULL) {
1413 if (VALUE_IS_ERROR (a))
1414 return 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,
1419 expr);
1421 b = gnm_expr_eval (expr->binary.value_b, pos, flags);
1422 if (b != NULL) {
1423 if (VALUE_IS_ERROR (b)) {
1424 value_release (a);
1425 return 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,
1430 expr);
1433 if (a == NULL) {
1434 if (b != NULL) {
1435 res = value_new_string (value_peek_string (b));
1436 value_release (b);
1437 } else
1438 res = value_new_string ("");
1439 } else if (b == NULL) {
1440 res = value_new_string (value_peek_string (a));
1441 value_release (a);
1442 } else {
1443 char *tmp = g_strconcat (value_peek_string (a),
1444 value_peek_string (b), NULL);
1445 res = value_new_string_nocopy (tmp);
1446 value_release (a);
1447 value_release (b);
1449 return res;
1451 case GNM_EXPR_OP_FUNCALL: {
1452 GnmFuncEvalInfo ei;
1453 ei.pos = pos;
1454 ei.func_call = &expr->func;
1455 ei.flags = flags;
1456 res = function_call_with_exprs (&ei);
1457 if (res == NULL)
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.
1466 if (pos->dep)
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);
1475 return res;
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);
1483 return a;
1485 return 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: {
1494 GnmCell *cell;
1495 GnmCellRef r;
1497 gnm_cellref_make_abs (&r, &expr->cellref.ref, pos);
1499 cell = sheet_cell_get (eval_sheet (r.sheet, pos->sheet),
1500 r.col, r.row);
1501 if (cell)
1502 gnm_cell_eval (cell);
1504 if (flags & GNM_EXPR_EVAL_WANT_REF) {
1505 return value_new_cellrange_unsafe (&r, &r);
1506 } else {
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)
1516 return res;
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) {
1531 int i;
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);
1540 return res;
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"));
1554 GnmExpr const *
1555 gnm_expr_simplify_if (GnmExpr const *expr)
1557 static GnmFunc *f_if = NULL;
1558 GnmExpr const *cond;
1559 gboolean c;
1561 g_return_val_if_fail (expr != NULL, NULL);
1563 if (GNM_EXPR_GET_OPER (expr) != GNM_EXPR_OP_FUNCALL)
1564 return NULL;
1566 if (!f_if)
1567 f_if = gnm_func_lookup ("if", NULL);
1569 if (expr->func.func != f_if || expr->func.argc != 3)
1570 return NULL;
1572 cond = expr->func.argv[0];
1573 if (GNM_EXPR_GET_OPER (cond) == GNM_EXPR_OP_CONSTANT) {
1574 GnmValue const *condval = cond->constant.value;
1575 gboolean err;
1576 c = value_get_as_bool (condval, &err);
1577 if (err)
1578 return NULL;
1579 } else
1580 return NULL;
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.
1597 static void
1598 do_expr_as_string (GnmExpr const *expr, int paren_level,
1599 GnmConventionsOut *out)
1601 static struct {
1602 char const name[4];
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;
1636 switch (op) {
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);
1669 else
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, ')');
1675 return;
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, ')');
1689 return;
1692 case GNM_EXPR_OP_FUNCALL:
1693 out->convs->output.func (out, &expr->func);
1694 return;
1696 case GNM_EXPR_OP_NAME:
1697 out->convs->output.name (out, &expr->name);
1698 return;
1700 case GNM_EXPR_OP_CELLREF:
1701 out->convs->output.cell_ref (out, &expr->cellref.ref, FALSE);
1702 return;
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);
1710 return;
1713 if (VALUE_IS_CELLRANGE (v)) {
1714 out->convs->output.range_ref (out, &v->v_range.cell);
1715 return;
1718 if (VALUE_IS_BOOLEAN (v) &&
1719 out->convs->output.boolean != NULL) {
1720 out->convs->output.boolean (out, v->v_bool.val);
1721 return;
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, ')');
1735 return;
1738 case GNM_EXPR_OP_ARRAY_CORNER:
1739 do_expr_as_string (expr->array_corner.expr, 0, out);
1740 return;
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;
1751 out->pp = &pp;
1752 do_expr_as_string (
1753 corner->base.texpr->expr->array_corner.expr,
1754 0, out);
1755 out->pp = real_pp;
1756 return;
1758 break;
1761 case GNM_EXPR_OP_SET:
1762 gnm_expr_list_as_string (expr->set.argc, expr->set.argv, out);
1763 return;
1766 g_string_append (target, "<ERROR>");
1769 void
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);
1778 char *
1779 gnm_expr_as_string (GnmExpr const *expr, GnmParsePos const *pp,
1780 GnmConventions const *convs)
1782 GnmConventionsOut out;
1783 GnmParsePos pp0;
1785 g_return_val_if_fail (expr != NULL, NULL);
1788 * Defaults for debugging only!
1790 if (!pp) {
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);
1795 pp = &pp0;
1797 if (!convs)
1798 convs = pp->sheet
1799 ? sheet_get_conventions (pp->sheet)
1800 : gnm_conventions_default;
1802 out.accum = g_string_new (NULL);
1803 out.pp = pp;
1804 out.convs = convs;
1805 do_expr_as_string (expr, 0, &out);
1806 return g_string_free (out.accum, FALSE);
1809 /****************************************************************************/
1811 static gboolean
1812 gnm_expr_is_err (GnmExpr const *expr, GnmStdError err)
1814 GnmStdError err2;
1816 if (GNM_EXPR_GET_OPER (expr) != GNM_EXPR_OP_CONSTANT)
1817 return FALSE;
1819 err2 = value_error_classify (expr->constant.value);
1820 return err == err2;
1824 * gnm_expr_get_constant:
1825 * @expr:
1827 * If this expression consists of just a constant, return it.
1829 GnmValue const *
1830 gnm_expr_get_constant (GnmExpr const *expr)
1832 if (GNM_EXPR_GET_OPER (expr) != GNM_EXPR_OP_CONSTANT)
1833 return NULL;
1835 return expr->constant.value;
1839 * gnm_expr_get_name:
1840 * @expr:
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)
1848 return NULL;
1850 return expr->name.name;
1855 * gnm_expr_get_cellref:
1856 * @expr:
1858 * If this expression consists of just a cell reference, return it.
1860 GnmCellRef const *
1861 gnm_expr_get_cellref (GnmExpr const *expr)
1863 if (GNM_EXPR_GET_OPER (expr) != GNM_EXPR_OP_CELLREF)
1864 return NULL;
1866 return &expr->cellref.ref;
1870 typedef struct {
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;
1885 Workbook *wb;
1886 gboolean hit_a = sheet_a && sheet_a->being_invalidated;
1887 gboolean hit_b = sheet_b && sheet_b->being_invalidated;
1888 int dir;
1890 if (!hit_a && !hit_b)
1891 return NULL;
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));
1914 static gboolean
1915 reloc_range (GnmExprRelocateInfo const *rinfo,
1916 Sheet const *start_sheet, Sheet const *end_sheet,
1917 GnmRange *rng)
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 */
1924 return FALSE;
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;
1938 return TRUE;
1941 if (rinfo->col_offset == 0) {
1942 if (start && rinfo->row_offset < range_height (rng)) {
1943 rng->start.row += rinfo->row_offset;
1944 return TRUE;
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;
1953 else
1954 rng->end.row += rinfo->row_offset;
1955 return TRUE;
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;
1963 return TRUE;
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;
1973 else
1974 rng->end.col += rinfo->col_offset;
1975 return TRUE;
1979 return FALSE;
1982 static void
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;
1991 else
1992 res->col = 0;
1994 res->row = ref->row;
1995 if (ref->row_relative) {
1996 if (rinfo->check_rels)
1997 res->row += rinfo->details->pos.eval.row;
1998 else
1999 res->row = 0;
2003 /* Return TRUE if @pos is out of bounds */
2004 static gboolean
2005 reloc_restore_cellref (RelocInfoInternal const *rinfo,
2006 GnmSheetSize const *ss, GnmCellPos const *pos,
2007 GnmCellRef *res)
2009 if (res->sheet == rinfo->details->origin_sheet) {
2010 res->sheet = rinfo->details->target_sheet;
2011 if (res->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)
2017 return TRUE;
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)
2028 return TRUE;
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;
2037 return FALSE;
2041 static GnmExpr const *
2042 reloc_cellrange (RelocInfoInternal const *rinfo, GnmValueRange const *v,
2043 gboolean sticky_end)
2045 GnmRange r;
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;
2074 if (full_col)
2075 r.end.row = start_ss->max_rows - 1;
2076 if (full_col_begin)
2077 r.start.row = 0;
2078 if (full_row)
2079 r.end.col = start_ss->max_cols - 1;
2080 if (full_row_begin)
2081 r.start.col = 0;
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))
2087 return NULL;
2088 return gnm_expr_new_constant (value_new_cellrange_unsafe (&res.a, &res.b));
2091 return NULL;
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));
2117 else
2118 return 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;
2128 GnmParsePos pos;
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);
2143 } else {
2145 * Do NOT rewrite the name.
2147 * Just invalidate the use of the name if the
2148 * name's expression, if relocated, would
2149 * become invalid.
2151 GnmExpr const *tmp =
2152 gnm_expr_relocate (nexpr->texpr->expr,
2153 rinfo);
2154 if (tmp && gnm_expr_is_err (tmp, GNM_ERROR_REF))
2155 return tmp;
2157 if (tmp)
2158 gnm_expr_free (tmp);
2160 return NULL;
2163 case GNM_EXPR_RELOCATE_COLS:
2164 case GNM_EXPR_RELOCATE_ROWS:
2165 return NULL;
2167 default:
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:
2176 if (ref->sheet &&
2177 ref->sheet->being_invalidated)
2178 return gnm_expr_new_constant (value_new_error_REF (NULL));
2179 return NULL;
2181 case GNM_EXPR_RELOCATE_MOVE_RANGE:
2182 case GNM_EXPR_RELOCATE_COLS:
2183 case GNM_EXPR_RELOCATE_ROWS: {
2184 GnmRange r;
2185 Sheet *sheet;
2186 GnmSheetSize const *ss;
2188 reloc_normalize_cellref (rinfo, ref, &sheet, &r.start);
2189 r.end = 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))
2198 return NULL;
2199 return gnm_expr_new_cellref (&res);
2201 return NULL;
2204 default:
2205 g_assert_not_reached ();
2208 return NULL;
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);
2222 default:
2223 g_assert_not_reached ();
2226 return NULL;
2228 default:
2229 return NULL;
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);
2240 GnmFunc *
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;
2249 GnmExpr const *
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];
2260 static void
2261 cellref_boundingbox (GnmCellRef const *cr, Sheet const *sheet, GnmRange *bound)
2263 GnmSheetSize const *ss;
2265 if (cr->sheet)
2266 sheet = cr->sheet;
2267 ss = gnm_sheet_get_size (sheet);
2269 if (cr->col_relative) {
2270 if (cr->col >= 0) {
2271 int const c = ss->max_cols - cr->col - 1;
2272 if (bound->end.col > c)
2273 bound->end.col = c;
2274 } else {
2275 int const c = -cr->col;
2276 if (bound->start.col < c)
2277 bound->start.col = c;
2280 if (cr->row_relative) {
2281 if (cr->row >= 0) {
2282 int const r = ss->max_rows - cr->row - 1;
2283 if (bound->end.row > r)
2284 bound->end.row = r;
2285 } else {
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) {
2299 *res = TRUE;
2300 data->stop = TRUE;
2302 return NULL;
2306 * gnm_expr_containts_subtotal :
2307 * @expr:
2309 * return TRUE if the expression calls the SUBTOTAL function
2311 gboolean
2312 gnm_expr_contains_subtotal (GnmExpr const *expr)
2314 gboolean res = FALSE;
2315 gnm_expr_walk (expr, cb_contains_subtotal, &res);
2316 return res;
2320 * gnm_expr_get_range:
2321 * @expr:
2323 * If this expression contains a single range return it.
2324 * Caller is responsible for value_releasing the result.
2326 GnmValue *
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);
2339 return NULL;
2341 case GNM_EXPR_OP_NAME:
2342 if (!expr_name_is_active (expr->name.name))
2343 return NULL;
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);
2349 default:
2350 return NULL;
2354 static gint
2355 gnm_insert_unique_value_cmp (gconstpointer a, gconstpointer b)
2357 return (value_equal (a,b) ? 0 : 1);
2362 static GSList *
2363 gnm_insert_unique_value (GSList *list, GnmValue *data)
2365 if (g_slist_find_custom (list, data,
2366 gnm_insert_unique_value_cmp)
2367 == NULL)
2368 return g_slist_prepend (list, data);
2369 value_release (data);
2370 return list;
2374 * gnm_expr_is_rangeref :
2375 * @expr:
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.
2381 gboolean
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:
2396 return TRUE;
2398 case GNM_EXPR_OP_CONSTANT:
2399 if (VALUE_IS_CELLRANGE (expr->constant.value))
2400 return TRUE;
2401 return FALSE;
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);
2406 return FALSE;
2408 case GNM_EXPR_OP_ARRAY_CORNER: /* I don't think this is possible */
2409 case GNM_EXPR_OP_ARRAY_ELEM:
2410 default :
2411 return FALSE;
2415 gboolean
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")) {
2421 if (NULL != r_in) {
2422 GnmExpr const *r = (expr->func.argc <= 0)
2423 ? NULL
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;
2429 } else
2430 r_in->col = r_in->row = 0; /* impossible */
2432 if (NULL != c_in) {
2433 GnmExpr const *c = (expr->func.argc <= 1)
2434 ? NULL
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;
2440 } else
2441 c_in->col = c_in->row = 0; /* impossible */
2443 return TRUE;
2447 /* Do we need anything else here ? */
2448 return FALSE;
2452 static GnmExpr const *
2453 do_expr_walk (GnmExpr const *expr, GnmExprWalkerFunc walker, GnmExprWalk *data)
2455 GnmExpr const *res;
2457 res = walker (expr, data);
2458 if (data->stop) {
2459 if (res) gnm_expr_free (res);
2460 return NULL;
2462 if (res)
2463 return 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);
2472 if (data->stop)
2473 return NULL;
2475 b = do_expr_walk (expr->binary.value_b, walker, data);
2476 if (data->stop) {
2477 if (a) gnm_expr_free (a);
2478 return NULL;
2481 if (!a && !b)
2482 return NULL;
2484 if (!a)
2485 a = gnm_expr_copy (expr->binary.value_a);
2486 else if (!b)
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);
2494 return a
2495 ? gnm_expr_new_unary (GNM_EXPR_GET_OPER (expr), a)
2496 : NULL;
2499 case GNM_EXPR_OP_FUNCALL: {
2500 gboolean any = FALSE;
2501 int i;
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);
2508 if (data->stop) {
2509 while (--i >= 0)
2510 if (argv[i])
2511 gnm_expr_free (argv[i]);
2512 any = FALSE;
2513 break;
2515 if (argv[i])
2516 any = TRUE;
2519 if (any) {
2520 int i;
2521 for (i = 0; i < argc; i++)
2522 if (!argv[i])
2523 argv[i] = gnm_expr_copy (expr->func.argv[i]);
2524 return gnm_expr_new_funcallv (expr->func.func,
2525 argc, argv);
2526 } else {
2527 g_free (argv);
2528 return NULL;
2531 case GNM_EXPR_OP_SET: {
2532 gboolean any = FALSE;
2533 int i;
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);
2540 if (data->stop) {
2541 while (--i >= 0)
2542 if (argv[i])
2543 gnm_expr_free (argv[i]);
2544 any = FALSE;
2545 break;
2547 if (argv[i])
2548 any = TRUE;
2551 if (any) {
2552 int i;
2553 for (i = 0; i < argc; i++)
2554 if (!argv[i])
2555 argv[i] = gnm_expr_copy (expr->set.argv[i]);
2556 return gnm_expr_new_setv (argc, argv);
2557 } else {
2558 g_free (argv);
2559 return NULL;
2563 case GNM_EXPR_OP_ARRAY_CORNER: {
2564 GnmExpr const *e = do_expr_walk (expr->array_corner.expr, walker, data);
2565 return e
2566 ? gnm_expr_new_array_corner (
2567 expr->array_corner.cols,
2568 expr->array_corner.rows, e)
2569 : NULL;
2572 default:
2573 return NULL;
2578 * gnm_expr_walk:
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.
2594 GnmExpr const *
2595 gnm_expr_walk (GnmExpr const *expr, GnmExprWalkerFunc walker, gpointer user)
2597 GnmExprWalk data;
2599 g_return_val_if_fail (expr != NULL, NULL);
2601 data.user = user;
2602 data.stop = FALSE;
2603 data.flags = 0;
2604 return do_expr_walk (expr, walker, &data);
2607 gboolean
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.
2619 void
2620 gnm_expr_list_unref (GnmExprList *list)
2622 GnmExprList *l;
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.
2634 GnmExprList *
2635 gnm_expr_list_copy (GnmExprList *list)
2637 GnmExprList *res = g_slist_copy (list); /* shallow */
2638 GnmExprList *l;
2640 for (l = res; l; l = l->next)
2641 l->data = (GnmExpr *) gnm_expr_copy (l->data);
2643 return res;
2647 void
2648 gnm_expr_list_as_string (int argc,
2649 GnmExprConstPtr const *argv,
2650 GnmConventionsOut *out)
2652 int i;
2653 gunichar arg_sep;
2654 if (out->convs->arg_sep)
2655 arg_sep = out->convs->arg_sep;
2656 else
2657 arg_sep = go_locale_get_arg_sep ();
2659 g_string_append_c (out->accum, '(');
2660 for (i = 0; i < argc; i++) {
2661 if (i != 0)
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, ')');
2668 static guint
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: {
2686 int i;
2687 for (i = 0; i < expr->func.argc; i++)
2688 h = (h * 3) ^ gnm_expr_hash (expr->func.argv[i]);
2689 return h;
2692 case GNM_EXPR_OP_SET: {
2693 int i;
2694 for (i = 0; i < expr->set.argc; i++)
2695 h = (h * 3) ^ gnm_expr_hash (expr->set.argv[i]);
2696 return h;
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));
2717 return h;
2721 /***************************************************************************/
2723 GnmExprSharer *
2724 gnm_expr_sharer_new (void)
2726 GnmExprSharer *es = g_new (GnmExprSharer, 1);
2727 es->nodes_in = 0;
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,
2734 NULL);
2735 es->ref_count = 1;
2736 return es;
2739 void
2740 gnm_expr_sharer_destroy (GnmExprSharer *es)
2742 if (!es || es->ref_count-- > 1)
2743 return;
2744 g_hash_table_destroy (es->exprs);
2745 g_free (es);
2748 static GnmExprSharer *
2749 gnm_expr_sharer_ref (GnmExprSharer *es)
2751 es->ref_count++;
2752 return es;
2755 GType
2756 gnm_expr_sharer_get_type (void)
2758 static GType t = 0;
2760 if (t == 0) {
2761 t = g_boxed_type_register_static ("GnmExprSharer",
2762 (GBoxedCopyFunc)gnm_expr_sharer_ref,
2763 (GBoxedFreeFunc)gnm_expr_sharer_destroy);
2765 return t;
2768 GnmExprTop const *
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);
2776 es->nodes_in++;
2778 /* Corners must not get shared. */
2779 if (GNM_EXPR_GET_OPER (texpr->expr) == GNM_EXPR_OP_ARRAY_CORNER)
2780 return texpr;
2782 shared = g_hash_table_lookup (es->exprs, texpr);
2783 if (shared) {
2784 gnm_expr_top_ref (shared);
2785 if (texpr->refcount == 1)
2786 es->nodes_killed++;
2787 gnm_expr_top_unref (texpr);
2788 return shared;
2791 gnm_expr_top_ref (texpr);
2792 g_hash_table_insert (es->exprs, (gpointer)texpr, (gpointer)texpr);
2793 es->nodes_stored++;
2795 return texpr;
2798 void
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 /***************************************************************************/
2808 GnmExprTop const *
2809 gnm_expr_top_new (GnmExpr const *expr)
2811 GnmExprTop *res;
2813 if (expr == NULL)
2814 return NULL;
2816 res = g_new (GnmExprTop, 1);
2817 res->magic = GNM_EXPR_TOP_MAGIC;
2818 res->hash = 0;
2819 res->refcount = 1;
2820 res->expr = expr;
2821 return res;
2824 GnmExprTop const *
2825 gnm_expr_top_new_constant (GnmValue *v)
2827 return gnm_expr_top_new (gnm_expr_new_constant (v));
2830 GnmExprTop const *
2831 gnm_expr_top_ref (GnmExprTop const *texpr)
2833 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), NULL);
2834 ((GnmExprTop *)texpr)->refcount++;
2835 return texpr;
2838 void
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);
2851 GType
2852 gnm_expr_top_get_type (void)
2854 static GType t = 0;
2856 if (t == 0) {
2857 t = g_boxed_type_register_static ("GnmExprTop",
2858 (GBoxedCopyFunc)gnm_expr_top_ref,
2859 (GBoxedFreeFunc)gnm_expr_top_unref);
2861 return t;
2864 gboolean
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;
2872 GnmExprTop const *
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));
2878 GnmExprTop const *
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);
2893 if (v)
2894 *pranges = gnm_insert_unique_value (*pranges, v);
2897 return NULL;
2901 * gnm_expr_top_get_ranges:
2902 * @texpr:
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.
2908 GSList *
2909 gnm_expr_top_get_ranges (GnmExprTop const *texpr)
2911 GSList *res = NULL;
2913 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), NULL);
2914 gnm_expr_walk (texpr->expr, cb_get_ranges, &res);
2915 return res;
2918 GnmValue *
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);
2926 char *
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);
2936 void
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);
2946 guint
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;
2957 return texpr->hash;
2960 gboolean
2961 gnm_expr_top_equal (GnmExprTop const *te1, GnmExprTop const *te2)
2963 if (te1 == te2)
2964 return TRUE;
2965 if (te1 == NULL || te2 == NULL)
2966 return FALSE;
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)
2972 return FALSE;
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
2997 GnmExprTop const *
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.
3019 GnmExprTop const *
3020 gnm_expr_top_relocate_sheet (GnmExprTop const *texpr,
3021 Sheet const *src,
3022 Sheet const *dst)
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);
3040 if (!res) {
3041 if (gnm_expr_top_is_array_corner (texpr))
3042 res = gnm_expr_top_new (gnm_expr_copy (texpr->expr));
3043 else
3044 gnm_expr_top_ref ((res = texpr));
3047 return res;
3050 gboolean
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)) {
3064 *res = TRUE;
3065 data->stop = TRUE;
3067 return NULL;
3070 gboolean
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);
3083 return res;
3087 static GnmValue *
3088 gnm_expr_top_eval_array_corner (GnmExprTop const *texpr,
3089 GnmEvalPos const *pos,
3090 GnmExprEvalFlags flags)
3092 GnmExpr const *expr = texpr->expr;
3093 GnmEvalPos pos2;
3094 GnmValue *a;
3096 pos2 = *pos;
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;
3106 if (a != NULL &&
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);
3116 static GnmValue *
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);
3125 GnmValue *a;
3127 if (!corner ||
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);
3135 if (a == NULL)
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)
3151 x = 0;
3152 if (y >= 1 && num_y == 1)
3153 y = 0;
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);
3163 GnmValue *
3164 gnm_expr_top_eval (GnmExprTop const *texpr,
3165 GnmEvalPos const *pos,
3166 GnmExprEvalFlags flags)
3168 GnmValue *res;
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.
3180 GnmEvalPos pos2;
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
3183 pos2 = *pos;
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);
3188 } else
3189 res = gnm_expr_eval (texpr->expr, pos, flags);
3190 gnm_app_recalc_finish ();
3192 return res;
3195 static GSList *
3196 gnm_insert_unique (GSList *list, gpointer data)
3198 if (g_slist_find (list, data) == NULL)
3199 return g_slist_prepend (list, data);
3200 return list;
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);
3211 break;
3213 case GNM_EXPR_OP_CONSTANT: {
3214 GnmValue const *v = expr->constant.value;
3215 if (!VALUE_IS_CELLRANGE (v))
3216 break;
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);
3221 break;
3224 default:
3225 break;
3228 return NULL;
3232 * gnm_expr_top_referenced_sheets:
3233 * @texpr:
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.
3240 GSList *
3241 gnm_expr_top_referenced_sheets (GnmExprTop const *texpr)
3243 GSList *res = NULL;
3245 g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), NULL);
3246 gnm_expr_walk (texpr->expr, cb_referenced_sheets, &res);
3247 return res;
3250 gboolean
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:
3259 * @texpr:
3261 * If this expression consists of just a constant, return it.
3263 GnmValue const *
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);
3271 GnmCellRef const *
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) {
3283 *user = expr;
3284 data->stop = TRUE;
3286 return NULL;
3290 * gnm_expr_top_first_funcall :
3291 * @texpr:
3294 GnmExpr const *
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);
3301 return res;
3304 struct cb_get_boundingbox {
3305 Sheet const *sheet;
3306 GnmRange *bound;
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);
3317 break;
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);
3326 break;
3329 default:
3330 break;
3333 return NULL;
3337 * gnm_expr_top_get_boundingbox :
3339 * Returns the range of cells in which the expression can be used without going
3340 * out of bounds.
3342 void
3343 gnm_expr_top_get_boundingbox (GnmExprTop const *texpr, Sheet const *sheet,
3344 GnmRange *bound)
3346 struct cb_get_boundingbox args;
3348 g_return_if_fail (GNM_IS_EXPR_TOP (texpr));
3350 range_init_full_sheet (bound, sheet);
3352 args.sheet = sheet;
3353 args.bound = bound;
3354 gnm_expr_walk (texpr->expr, cb_get_boundingbox, &args);
3357 gboolean
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);
3365 gboolean
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;
3372 void
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);
3378 if (cols)
3379 *cols = texpr->expr->array_corner.cols;
3380 if (rows)
3381 *rows = texpr->expr->array_corner.rows;
3384 GnmValue *
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;
3392 GnmExpr const *
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;
3400 gboolean
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)
3406 return FALSE;
3408 if (x) *x = texpr->expr->array_elem.x;
3409 if (y) *y = texpr->expr->array_elem.y;
3410 return TRUE;
3413 gboolean
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);
3420 GnmExprTop const *
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);
3436 default:
3437 return NULL;
3441 /****************************************************************************/
3443 #if USE_EXPR_POOLS
3444 typedef union {
3445 guint32 oper_and_refcount;
3446 GnmExprConstant constant;
3447 GnmExprFunction func;
3448 GnmExprUnary unary;
3449 GnmExprBinary binary;
3450 GnmExprArrayElem array_elem;
3451 GnmExprSet set;
3452 } GnmExprSmall;
3453 typedef union {
3454 guint32 oper_and_refcount;
3455 GnmExprName name;
3456 GnmExprCellRef cellref;
3457 GnmExprArrayCorner array_corner;
3458 } GnmExprBig;
3459 #endif
3461 void
3462 _gnm_expr_init (void)
3464 #if 0
3465 GnmExpr e;
3467 #if USE_EXPR_POOLS
3468 /* 12 is an excellent size for a pool. */
3469 g_print ("sizeof(GnmExprSmall) = %d\n", (int)sizeof (GnmExprSmall));
3470 g_print ("sizeof(GnmExprBig) = %d\n", (int)sizeof (GnmExprBig));
3471 #endif
3472 g_print ("sizeof(e.func) = %d\n", (int)sizeof (e.func));
3473 g_print ("sizeof(e.unary) = %d\n", (int)sizeof (e.unary));
3474 g_print ("sizeof(e.binary) = %d\n", (int)sizeof (e.binary));
3475 g_print ("sizeof(e.name) = %d\n", (int)sizeof (e.name));
3476 g_print ("sizeof(e.cellref) = %d\n", (int)sizeof (e.cellref));
3477 g_print ("sizeof(e.array_corner) = %d\n", (int)sizeof (e.array_corner));
3478 g_print ("sizeof(e.array_elem) = %d\n", (int)sizeof (e.array_elem));
3479 g_print ("sizeof(e.set) = %d\n", (int)sizeof (e.set));
3480 #endif
3481 #if USE_EXPR_POOLS
3482 expression_pool_small =
3483 go_mem_chunk_new ("expression pool for small nodes",
3484 sizeof (GnmExprSmall),
3485 16 * 1024 - 128);
3486 expression_pool_big =
3487 go_mem_chunk_new ("expression pool for big nodes",
3488 sizeof (GnmExprBig),
3489 16 * 1024 - 128);
3490 #endif
3493 #if USE_EXPR_POOLS
3494 static void
3495 cb_expression_pool_leak (gpointer data, G_GNUC_UNUSED gpointer user)
3497 GnmExpr const *expr = data;
3498 GnmParsePos pp;
3499 char *s;
3501 pp.eval.col = 0;
3502 pp.eval.row = 0;
3503 pp.sheet = NULL;
3504 pp.wb = NULL;
3505 s = gnm_expr_as_string (expr, &pp, NULL);
3506 g_printerr ("Leaking expression at %p: %s.\n", (void *)expr, s);
3507 g_free (s);
3509 #endif
3511 void
3512 _gnm_expr_shutdown (void)
3514 #if USE_EXPR_POOLS
3515 go_mem_chunk_foreach_leak (expression_pool_small, cb_expression_pool_leak, NULL);
3516 go_mem_chunk_destroy (expression_pool_small, FALSE);
3517 expression_pool_small = NULL;
3519 go_mem_chunk_foreach_leak (expression_pool_big, cb_expression_pool_leak, NULL);
3520 go_mem_chunk_destroy (expression_pool_big, FALSE);
3521 expression_pool_big = NULL;
3522 #endif
3525 /****************************************************************************/