expr.c 81.8 KB
Newer Older
1
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
Miguel de Icaza's avatar
Miguel de Icaza committed
2
/*
3
 * expr.c : Expression evaluation in Gnumeric
Miguel de Icaza's avatar
Miguel de Icaza committed
4
 *
5
 * Copyright (C) 2001-2006 Jody Goldberg (jody@gnome.org)
6
 * Copyright (C) 1998-2000 Miguel de Icaza (miguel@gnu.org)
Morten Welinder's avatar
Morten Welinder committed
7
 * Copyright (C) 2000-2009 Morten Welinder (terra@gnome.org)
8 9 10 11 12 13 14 15 16 17 18 19
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
J.H.M. Dassen (Ray)'s avatar
J.H.M. Dassen (Ray) committed
20
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
21
 * USA
Miguel de Icaza's avatar
Miguel de Icaza committed
22
 */
23
#include <gnumeric-config.h>
24
#include <glib/gi18n-lib.h>
25
#include "gnumeric.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
26
#include "expr.h"
27

28
#include "expr-impl.h"
29
#include "expr-name.h"
30
#include "dependent.h"
31
#include "application.h"
32
#include "func.h"
Jody Goldberg's avatar
Jody Goldberg committed
33
#include "cell.h"
Jody Goldberg's avatar
Jody Goldberg committed
34
#include "sheet.h"
35
#include "value.h"
36
#include "parse-util.h"
37
#include "ranges.h"
38
#include "number-match.h"
39
#include "workbook.h"
Jeffrey Stedfast's avatar
Jeffrey Stedfast committed
40
#include "gutils.h"
41
#include "parse-util.h"
42
#include "mathfunc.h"
43

44
#include <goffice/goffice.h>
Jody Goldberg's avatar
Jody Goldberg committed
45 46 47
#include <math.h>
#include <string.h>
#include <stdlib.h>
48

49 50 51 52 53 54 55 56 57
/*
 * Using pools here probably does not save anything, but it's a darn
 * good debugging tool.
 */
#ifndef USE_EXPR_POOLS
#define USE_EXPR_POOLS 1
#endif

#if USE_EXPR_POOLS
58 59
/* Memory pools for expressions.  */
static GOMemChunk *expression_pool_small, *expression_pool_big;
60 61
#define CHUNK_ALLOC(T,p) ((T*)go_mem_chunk_alloc (p))
#define CHUNK_FREE(p,v) go_mem_chunk_free ((p), (v))
62 63 64 65 66
#else
#define CHUNK_ALLOC(T,c) g_new (T,1)
#define CHUNK_FREE(p,v) g_free ((v))
#endif

67 68
/***************************************************************************/

Jody Goldberg's avatar
Jody Goldberg committed
69 70 71 72 73 74
/**
 * gnm_expr_new_constant :
 * @v :
 *
 * Absorbs the value.
 **/
75
GnmExpr const *
Jody Goldberg's avatar
Jody Goldberg committed
76
gnm_expr_new_constant (GnmValue *v)
77
{
78
	GnmExprConstant *ans;
79

80 81
	g_return_val_if_fail (v != NULL, NULL);

82
	ans = CHUNK_ALLOC (GnmExprConstant, expression_pool_small);
83 84
	if (!ans)
		return NULL;
85
	gnm_expr_constant_init (ans, v);
86

87
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
88 89
}

Jody Goldberg's avatar
Jody Goldberg committed
90 91
/***************************************************************************/

92 93
static GnmExpr const *
gnm_expr_new_funcallv (GnmFunc *func, int argc, GnmExprConstPtr *argv)
94
{
95
	GnmExprFunction *ans;
Jody Goldberg's avatar
Jody Goldberg committed
96
	g_return_val_if_fail (func, NULL);
97

98
	ans = CHUNK_ALLOC (GnmExprFunction, expression_pool_small);
99

100
	ans->oper = GNM_EXPR_OP_FUNCALL;
Jody Goldberg's avatar
Jody Goldberg committed
101
	gnm_func_ref (func);
102
	ans->func = func;
103 104
	ans->argc = argc;
	ans->argv = argv;
105

106
	return (GnmExpr *)ans;
107
}
108

109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
GnmExpr const *
gnm_expr_new_funcall (GnmFunc *func, GnmExprList *arg_list)
{
	GnmExprList *arg_list0 = arg_list;
	int argc = gnm_expr_list_length (arg_list);
	GnmExprConstPtr *argv = argc ? g_new (GnmExprConstPtr, argc) : NULL;
	int i;

	for (i = 0; arg_list; i++, arg_list = arg_list->next)
		argv[i] = arg_list->data;
	gnm_expr_list_free (arg_list0);

	return gnm_expr_new_funcallv (func, argc, argv);
}

Morten Welinder's avatar
Morten Welinder committed
124 125 126 127
GnmExpr const *
gnm_expr_new_funcall1 (GnmFunc *func,
		       GnmExpr const *arg0)
{
128 129 130
	GnmExprConstPtr *argv = g_new (GnmExprConstPtr, 1);
	argv[0] = arg0;
	return gnm_expr_new_funcallv (func, 1, argv);
Morten Welinder's avatar
Morten Welinder committed
131 132 133 134 135 136 137
}

GnmExpr const *
gnm_expr_new_funcall2 (GnmFunc *func,
		       GnmExpr const *arg0,
		       GnmExpr const *arg1)
{
138 139 140 141
	GnmExprConstPtr *argv = g_new (GnmExprConstPtr, 2);
	argv[0] = arg0;
	argv[1] = arg1;
	return gnm_expr_new_funcallv (func, 2, argv);
Morten Welinder's avatar
Morten Welinder committed
142 143 144 145 146 147 148 149
}

GnmExpr const *
gnm_expr_new_funcall3 (GnmFunc *func,
		       GnmExpr const *arg0,
		       GnmExpr const *arg1,
		       GnmExpr const *arg2)
{
150 151 152 153 154
	GnmExprConstPtr *argv = g_new (GnmExprConstPtr, 3);
	argv[0] = arg0;
	argv[1] = arg1;
	argv[2] = arg2;
	return gnm_expr_new_funcallv (func, 3, argv);
Morten Welinder's avatar
Morten Welinder committed
155 156
}

157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
GnmExpr const *
gnm_expr_new_funcall4 (GnmFunc *func,
		       GnmExpr const *arg0,
		       GnmExpr const *arg1,
		       GnmExpr const *arg2,
		       GnmExpr const *arg3)
{
	GnmExprConstPtr *argv = g_new (GnmExprConstPtr, 4);
	argv[0] = arg0;
	argv[1] = arg1;
	argv[2] = arg2;
	argv[3] = arg3;
	return gnm_expr_new_funcallv (func, 4, argv);
}

172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
GnmExpr const *
gnm_expr_new_funcall5 (GnmFunc *func,
		       GnmExpr const *arg0,
		       GnmExpr const *arg1,
		       GnmExpr const *arg2,
		       GnmExpr const *arg3,
		       GnmExpr const *arg4)
{
	GnmExprConstPtr *argv = g_new (GnmExprConstPtr, 5);
	argv[0] = arg0;
	argv[1] = arg1;
	argv[2] = arg2;
	argv[3] = arg3;
	argv[4] = arg4;
	return gnm_expr_new_funcallv (func, 5, argv);
}

Morten Welinder's avatar
Morten Welinder committed
189

Jody Goldberg's avatar
Jody Goldberg committed
190 191
/***************************************************************************/

192 193
GnmExpr const *
gnm_expr_new_unary  (GnmExprOp op, GnmExpr const *e)
Morten Welinder's avatar
Morten Welinder committed
194
{
195
	GnmExprUnary *ans;
Morten Welinder's avatar
Morten Welinder committed
196

197
	ans = CHUNK_ALLOC (GnmExprUnary, expression_pool_small);
198 199 200
	if (!ans)
		return NULL;

201
	ans->oper = op;
202
	ans->value = e;
203

204
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
205 206
}

Jody Goldberg's avatar
Jody Goldberg committed
207 208
/***************************************************************************/

209 210
GnmExpr const *
gnm_expr_new_binary (GnmExpr const *l, GnmExprOp op, GnmExpr const *r)
Morten Welinder's avatar
Morten Welinder committed
211
{
212
	GnmExprBinary *ans;
Morten Welinder's avatar
Morten Welinder committed
213

214
	ans = CHUNK_ALLOC (GnmExprBinary, expression_pool_small);
215 216
	if (!ans)
		return NULL;
217

218
	ans->oper = op;
219 220
	ans->value_a = l;
	ans->value_b = r;
221

222
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
223 224
}

Jody Goldberg's avatar
Jody Goldberg committed
225 226
/***************************************************************************/

227 228
GnmExpr const *
gnm_expr_new_name (GnmNamedExpr *name,
229
		   Sheet *optional_scope, Workbook *optional_wb_scope)
Morten Welinder's avatar
Morten Welinder committed
230
{
231
	GnmExprName *ans;
Morten Welinder's avatar
Morten Welinder committed
232

233
	ans = CHUNK_ALLOC (GnmExprName, expression_pool_big);
234 235
	if (!ans)
		return NULL;
236

237
	ans->oper = GNM_EXPR_OP_NAME;
238
	ans->name = name;
239
	expr_name_ref (name);
240

241 242 243
	ans->optional_scope = optional_scope;
	ans->optional_wb_scope = optional_wb_scope;

244
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
245
}
246

Jody Goldberg's avatar
Jody Goldberg committed
247 248
/***************************************************************************/

249
GnmExpr const *
Jody Goldberg's avatar
Jody Goldberg committed
250
gnm_expr_new_cellref (GnmCellRef const *cr)
251
{
252
	GnmExprCellRef *ans;
253

254
	ans = CHUNK_ALLOC (GnmExprCellRef, expression_pool_big);
255 256
	if (!ans)
		return NULL;
257

258
	ans->oper = GNM_EXPR_OP_CELLREF;
259 260
	ans->ref = *cr;

261
	return (GnmExpr *)ans;
262 263
}

Jody Goldberg's avatar
Jody Goldberg committed
264 265
/***************************************************************************/

266 267 268 269 270 271 272 273
static gboolean
gnm_expr_is_array (GnmExpr const *expr)
{
	return expr &&
		(GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_ARRAY_ELEM ||
		 GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_ARRAY_CORNER);
}

Jody Goldberg's avatar
Jody Goldberg committed
274
/**
275
 * gnm_expr_new_array_corner :
Jody Goldberg's avatar
Jody Goldberg committed
276 277 278 279 280 281
 * @cols :
 * @rows :
 * @expr : optionally NULL.
 *
 * Absorb a referernce to @expr if it is non NULL.
 **/
282
static GnmExpr const *
283
gnm_expr_new_array_corner(int cols, int rows, GnmExpr const *expr)
284
{
285
	GnmExprArrayCorner *ans;
286

287 288
	g_return_val_if_fail (!gnm_expr_is_array (expr), NULL);

289
	ans = CHUNK_ALLOC (GnmExprArrayCorner, expression_pool_big);
290 291
	if (ans == NULL)
		return NULL;
292

293
	ans->oper = GNM_EXPR_OP_ARRAY_CORNER;
294 295
	ans->rows = rows;
	ans->cols = cols;
296 297 298 299 300
	ans->value = NULL;
	ans->expr = expr;
	return (GnmExpr *)ans;
}

301
static GnmExpr const *
302 303 304 305
gnm_expr_new_array_elem  (int x, int y)
{
	GnmExprArrayElem *ans;

306
	ans = CHUNK_ALLOC (GnmExprArrayElem, expression_pool_small);
307 308 309
	if (ans == NULL)
		return NULL;

310
	ans->oper = GNM_EXPR_OP_ARRAY_ELEM;
311 312
	ans->x = x;
	ans->y = y;
313
	return (GnmExpr *)ans;
314 315
}

Jody Goldberg's avatar
Jody Goldberg committed
316 317
/***************************************************************************/

318 319
static GnmExpr const *
gnm_expr_new_setv (int argc, GnmExprConstPtr *argv)
Jody Goldberg's avatar
Jody Goldberg committed
320
{
321 322
	GnmExprSet *ans = CHUNK_ALLOC (GnmExprSet, expression_pool_small);

323
	ans->oper = GNM_EXPR_OP_SET;
324 325 326 327
	ans->argc = argc;
	ans->argv = argv;

	return (GnmExpr *)ans;
Jody Goldberg's avatar
Jody Goldberg committed
328 329
}

330 331
GnmExpr const *
gnm_expr_new_set (GnmExprList *set)
332
{
333 334 335
	int i, argc;
	GnmExprConstPtr *argv;
	GnmExprList *set0 = set;
336

337 338 339 340 341
	argc = gnm_expr_list_length (set);
	argv = argc ? g_new (GnmExprConstPtr, argc) : NULL;
	for (i = 0; set; i++, set = set->next)
		argv[i] = set->data;
	gnm_expr_list_free (set0);
342

343
	return gnm_expr_new_setv (argc, argv);
344 345
}

Jody Goldberg's avatar
Jody Goldberg committed
346
/***************************************************************************/
347 348 349 350 351 352 353

/**
 * gnm_expr_new_range_ctor:
 * @l: start range
 * @r: end range
 *
 * This function builds a range constructor or something simpler,
Morten Welinder's avatar
Morten Welinder committed
354
 * but equivalent, if the arguments allow it.
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
 *
 * Note: this takes ownership of @l and @r and may delete them.
 **/
GnmExpr const *
gnm_expr_new_range_ctor (GnmExpr const *l, GnmExpr const *r)
{
	GnmValue *v;

	g_return_val_if_fail (l != NULL, NULL);
	g_return_val_if_fail (r != NULL, NULL);

	if (GNM_EXPR_GET_OPER (l) != GNM_EXPR_OP_CELLREF)
		goto fallback;
	if (GNM_EXPR_GET_OPER (r) != GNM_EXPR_OP_CELLREF)
		goto fallback;

	v = value_new_cellrange_unsafe (&l->cellref.ref, &r->cellref.ref);
	gnm_expr_free (l);
	gnm_expr_free (r);
	return gnm_expr_new_constant (v);

 fallback:
	return gnm_expr_new_binary (l, GNM_EXPR_OP_RANGE_CTOR, r);
}

/***************************************************************************/
Jody Goldberg's avatar
Jody Goldberg committed
381

382 383
GnmExpr const *
gnm_expr_copy (GnmExpr const *expr)
384
{
385 386
	g_return_val_if_fail (expr != NULL, NULL);

387 388 389 390 391 392 393 394
	switch (GNM_EXPR_GET_OPER (expr)) {
	case GNM_EXPR_OP_RANGE_CTOR:
	case GNM_EXPR_OP_INTERSECT:
	case GNM_EXPR_OP_ANY_BINARY:
		return gnm_expr_new_binary
			(gnm_expr_copy (expr->binary.value_a),
			 GNM_EXPR_GET_OPER (expr),
			 gnm_expr_copy (expr->binary.value_b));
395

396 397 398 399
	case GNM_EXPR_OP_ANY_UNARY:
		return gnm_expr_new_unary
			(GNM_EXPR_GET_OPER (expr),
			 gnm_expr_copy (expr->unary.value));
400

401 402 403 404
	case GNM_EXPR_OP_FUNCALL: {
		GnmExprConstPtr *argv =
			g_new (GnmExprConstPtr, expr->func.argc);
		int i;
405

406 407
		for (i = 0; i < expr->func.argc; i++)
			argv[i] = gnm_expr_copy (expr->func.argv[i]);
408

409 410 411 412 413
		return gnm_expr_new_funcallv
			(expr->func.func,
			 expr->func.argc,
			 argv);
	}
414

415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
	case GNM_EXPR_OP_NAME:
		return gnm_expr_new_name
			(expr->name.name,
			 expr->name.optional_scope,
			 expr->name.optional_wb_scope);

	case GNM_EXPR_OP_CONSTANT:
		return gnm_expr_new_constant
			(value_dup (expr->constant.value));

	case GNM_EXPR_OP_CELLREF:
		return gnm_expr_new_cellref (&expr->cellref.ref);

	case GNM_EXPR_OP_ARRAY_CORNER:
		return gnm_expr_new_array_corner
			(expr->array_corner.cols, expr->array_corner.rows,
			 gnm_expr_copy (expr->array_corner.expr));

	case GNM_EXPR_OP_ARRAY_ELEM:
		return gnm_expr_new_array_elem
			(expr->array_elem.x,
			 expr->array_elem.y);

	case GNM_EXPR_OP_SET: {
		GnmExprConstPtr *argv =
			g_new (GnmExprConstPtr, expr->set.argc);
		int i;

		for (i = 0; i < expr->set.argc; i++)
			argv[i] = gnm_expr_copy (expr->set.argv[i]);

		return gnm_expr_new_setv
			(expr->set.argc,
			 argv);
	}

#ifndef DEBUG_SWITCH_ENUM
	default:
		g_assert_not_reached ();
		break;
#endif
	}
}

/*
 * gnm_expr_free:
 */
void
gnm_expr_free (GnmExpr const *expr)
{
	g_return_if_fail (expr != NULL);
Morten Welinder's avatar
Morten Welinder committed
466

467
	switch (GNM_EXPR_GET_OPER (expr)) {
468
	case GNM_EXPR_OP_RANGE_CTOR:
469
	case GNM_EXPR_OP_INTERSECT:
470
	case GNM_EXPR_OP_ANY_BINARY:
471 472
		gnm_expr_free (expr->binary.value_a);
		gnm_expr_free (expr->binary.value_b);
473
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
474
		break;
475

476 477 478 479
	case GNM_EXPR_OP_FUNCALL: {
		int i;

		for (i = 0; i < expr->func.argc; i++)
480
			gnm_expr_free (expr->func.argv[i]);
Morten Welinder's avatar
Morten Welinder committed
481
		g_free (expr->func.argv);
Jody Goldberg's avatar
Jody Goldberg committed
482
		gnm_func_unref (expr->func.func);
483
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
484
		break;
485
	}
486

487
	case GNM_EXPR_OP_NAME:
488
		expr_name_unref (expr->name.name);
489
		CHUNK_FREE (expression_pool_big, (gpointer)expr);
490 491
		break;

492
	case GNM_EXPR_OP_CONSTANT:
Jody Goldberg's avatar
Jody Goldberg committed
493
		value_release ((GnmValue *)expr->constant.value);
494
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
495 496 497
		break;

	case GNM_EXPR_OP_CELLREF:
498
		CHUNK_FREE (expression_pool_big, (gpointer)expr);
499 500
		break;

501
	case GNM_EXPR_OP_ANY_UNARY:
502
		gnm_expr_free (expr->unary.value);
503
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
504
		break;
505

506
	case GNM_EXPR_OP_ARRAY_CORNER:
507
		value_release (expr->array_corner.value);
508
		gnm_expr_free (expr->array_corner.expr);
509
		CHUNK_FREE (expression_pool_big, (gpointer)expr);
510 511 512
		break;

	case GNM_EXPR_OP_ARRAY_ELEM:
513
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
Jody Goldberg's avatar
Jody Goldberg committed
514
		break;
515

516 517 518 519
	case GNM_EXPR_OP_SET: {
		int i;

		for (i = 0; i < expr->set.argc; i++)
520
			gnm_expr_free (expr->set.argv[i]);
Morten Welinder's avatar
Morten Welinder committed
521
		g_free (expr->set.argv);
522
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
523
		break;
524
	}
525 526

#ifndef DEBUG_SWITCH_ENUM
527
	default:
528
		g_assert_not_reached ();
529
		break;
530
#endif
531
	}
532 533
}

Jody Goldberg's avatar
Jody Goldberg committed
534
/**
535
 * gnm_expr_equal : Returns TRUE if the supplied expressions are exactly the
Jody Goldberg's avatar
Jody Goldberg committed
536
 *   same.  No eval position is used to see if they are effectively the same.
Morten Welinder's avatar
Morten Welinder committed
537
 *   Named expressions must refer the same name, having equivalent names is
Jody Goldberg's avatar
Jody Goldberg committed
538 539
 *   insufficeient.
 */
540
static gboolean
541
gnm_expr_equal (GnmExpr const *a, GnmExpr const *b)
Jody Goldberg's avatar
Jody Goldberg committed
542 543 544 545 546 547 548
{
	if (a == b)
		return TRUE;

	g_return_val_if_fail (a != NULL, FALSE);
	g_return_val_if_fail (b != NULL, FALSE);

549
	if (GNM_EXPR_GET_OPER (a) != GNM_EXPR_GET_OPER (b))
Jody Goldberg's avatar
Jody Goldberg committed
550 551
		return FALSE;

552
	switch (GNM_EXPR_GET_OPER (a)) {
553
	case GNM_EXPR_OP_RANGE_CTOR:
554
	case GNM_EXPR_OP_INTERSECT:
555 556 557
	case GNM_EXPR_OP_ANY_BINARY:
		return	gnm_expr_equal (a->binary.value_a, b->binary.value_a) &&
			gnm_expr_equal (a->binary.value_b, b->binary.value_b);
Jody Goldberg's avatar
Jody Goldberg committed
558

559 560
	case GNM_EXPR_OP_ANY_UNARY:
		return gnm_expr_equal (a->unary.value, b->unary.value);
Jody Goldberg's avatar
Jody Goldberg committed
561

562 563 564 565 566 567 568 569 570 571 572 573
	case GNM_EXPR_OP_FUNCALL: {
		int i;

		if (a->func.func != b->func.func ||
		    a->func.argc != b->func.argc)
			return FALSE;

		for (i = 0; i < a->func.argc; i++)
			if (!gnm_expr_equal (a->func.argv[i], b->func.argv[i]))
				return FALSE;
		return TRUE;
	}
Jody Goldberg's avatar
Jody Goldberg committed
574

575
	case GNM_EXPR_OP_NAME:
576 577 578
		return	a->name.name == b->name.name &&
			a->name.optional_scope == b->name.optional_scope &&
			a->name.optional_wb_scope == b->name.optional_wb_scope;
Jody Goldberg's avatar
Jody Goldberg committed
579

580
	case GNM_EXPR_OP_CELLREF:
581
		return gnm_cellref_equal (&a->cellref.ref, &b->cellref.ref);
Jody Goldberg's avatar
Jody Goldberg committed
582

583 584
	case GNM_EXPR_OP_CONSTANT:
		return value_equal (a->constant.value, b->constant.value);
Jody Goldberg's avatar
Jody Goldberg committed
585

586 587 588
	case GNM_EXPR_OP_ARRAY_CORNER: {
		GnmExprArrayCorner const *aa = &a->array_corner;
		GnmExprArrayCorner const *ab = &b->array_corner;
Jody Goldberg's avatar
Jody Goldberg committed
589 590 591

		return	aa->cols == ab->cols &&
			aa->rows == ab->rows &&
592 593 594 595 596 597
			gnm_expr_equal (aa->expr, ab->expr);
	}
	case GNM_EXPR_OP_ARRAY_ELEM: {
		GnmExprArrayElem const *aa = &a->array_elem;
		GnmExprArrayElem const *ab = &b->array_elem;
		return	aa->x == ab->x && aa->y == ab->y;
Jody Goldberg's avatar
Jody Goldberg committed
598 599
	}

600 601 602 603 604 605 606 607 608 609 610
	case GNM_EXPR_OP_SET: {
		int i;

		if (a->set.argc != b->set.argc)
			return FALSE;

		for (i = 0; i < a->set.argc; i++)
			if (!gnm_expr_equal (a->set.argv[i], b->set.argv[i]))
				return FALSE;
		return TRUE;
	}
Jody Goldberg's avatar
Jody Goldberg committed
611 612 613 614 615
	}

	return FALSE;
}

616
static GnmCell *
617 618
array_elem_get_corner (GnmExprArrayElem const *elem,
		       Sheet const *sheet, GnmCellPos const *pos)
619
{
620
	GnmCell *corner = sheet_cell_get (sheet,
621
		pos->col - elem->x, pos->row - elem->y);
622 623 624

	/* Sanity check incase the corner gets removed for some reason */
	g_return_val_if_fail (corner != NULL, NULL);
625
	g_return_val_if_fail (gnm_cell_has_expr (corner), NULL);
626 627
	g_return_val_if_fail (corner->base.texpr != (void *)0xdeadbeef, NULL);
	g_return_val_if_fail (IS_GNM_EXPR_TOP (corner->base.texpr), NULL);
628 629 630 631 632

	return corner;
}

static gboolean
Jody Goldberg's avatar
Jody Goldberg committed
633
gnm_expr_extract_ref (GnmRangeRef *res, GnmExpr const *expr,
Morten Welinder's avatar
Morten Welinder committed
634
		      GnmEvalPos const *pos, GnmExprEvalFlags flags)
635
{
636
	switch (GNM_EXPR_GET_OPER (expr)) {
637 638
	case GNM_EXPR_OP_FUNCALL : {
		gboolean failed = TRUE;
Jody Goldberg's avatar
Jody Goldberg committed
639
		GnmValue *v;
640
		GnmFuncEvalInfo ei;
641

642
		ei.pos = pos;
643
		ei.func_call = &expr->func;
644
		v = function_call_with_exprs (&ei, flags);
645 646

		if (v != NULL) {
Jody Goldberg's avatar
Jody Goldberg committed
647 648
			if (v->type == VALUE_CELLRANGE) {
				*res = v->v_range.cell;
649 650 651 652 653 654 655 656
				failed = FALSE;
			}
			value_release (v);
		}
		return failed;
	}

	case GNM_EXPR_OP_CELLREF :
Jody Goldberg's avatar
Jody Goldberg committed
657 658
		res->a = expr->cellref.ref;
		res->b = expr->cellref.ref;
659 660 661
		return FALSE;

	case GNM_EXPR_OP_CONSTANT: {
Jody Goldberg's avatar
Jody Goldberg committed
662
		GnmValue const *v = expr->constant.value;
Jody Goldberg's avatar
Jody Goldberg committed
663 664
		if (v->type == VALUE_CELLRANGE) {
			*res = v->v_range.cell;
665 666 667 668 669 670
			return FALSE;
		}
		return TRUE;
	}

	case GNM_EXPR_OP_NAME:
Morten Welinder's avatar
Morten Welinder committed
671
		if (!expr_name_is_active (expr->name.name))
672
			return TRUE;
673 674
		return gnm_expr_extract_ref (res, expr->name.name->texpr->expr,
					     pos, flags);
675 676 677 678 679 680
	default :
		break;
	}
	return TRUE;
}

Jody Goldberg's avatar
Jody Goldberg committed
681 682
static inline GnmValue *
handle_empty (GnmValue *res, GnmExprEvalFlags flags)
683 684 685 686 687
{
	if (res == NULL)
		return (flags & GNM_EXPR_EVAL_PERMIT_EMPTY)
		    ? NULL : value_new_int (0);

688
	if (VALUE_IS_EMPTY (res)) {
689 690 691 692 693 694 695
		value_release (res);
		return (flags & GNM_EXPR_EVAL_PERMIT_EMPTY)
		    ? NULL : value_new_int (0);
	}
	return res;
}

Jody Goldberg's avatar
Jody Goldberg committed
696 697
/**
 * value_intersection :
698
 * @v   : a VALUE_CELLRANGE or VALUE_ARRAY
Morten Welinder's avatar
Morten Welinder committed
699
 * @pos :
Jody Goldberg's avatar
Jody Goldberg committed
700 701 702 703 704 705 706 707 708 709 710 711 712 713 714
 *
 * Handle the implicit union of a single row or column with the eval position.
 *
 * NOTE : We do not need to know if this is expression is being evaluated as an
 * array or not because we can differentiate based on the required type for the
 * argument.
 *
 * Always release the value passed in.
 *
 * Return value:
 *     If the intersection succeeded return a duplicate of the value
 *     at the intersection point.  This value needs to be freed.
 *     NULL if there is no intersection
 * Returns the upper left corner of an array.
 **/
Jody Goldberg's avatar
Jody Goldberg committed
715
static GnmValue *
Morten Welinder's avatar
Morten Welinder committed
716
value_intersection (GnmValue *v, GnmEvalPos const *pos)
Jody Goldberg's avatar
Jody Goldberg committed
717
{
Jody Goldberg's avatar
Jody Goldberg committed
718 719
	GnmValue *res = NULL;
	GnmRange r;
Jody Goldberg's avatar
Jody Goldberg committed
720 721 722 723
	Sheet *start_sheet, *end_sheet;
	gboolean found = FALSE;

	if (v->type == VALUE_ARRAY) {
724 725 726
		res = (v->v_array.x == 0 || v->v_array.y == 0)
			? value_new_error_VALUE (NULL)
			: value_dup (v->v_array.vals[0][0]);
Jody Goldberg's avatar
Jody Goldberg committed
727 728 729 730 731
		value_release (v);
		return res;
	}

	/* inverted ranges */
732
	gnm_rangeref_normalize (&v->v_range.cell, pos, &start_sheet, &end_sheet, &r);
Jody Goldberg's avatar
Jody Goldberg committed
733 734 735 736 737 738
	value_release (v);

	if (start_sheet == end_sheet || end_sheet == NULL) {
		int col = pos->eval.col;
		int row = pos->eval.row;

739 740 741 742 743 744
		if (pos->dep && !dependent_is_cell (pos->dep)) {
			/* See bug #142412.  */
			col = r.start.col;
			row = r.start.row;
			found = TRUE;
		} else if (r.start.row == r.end.row) {
Jody Goldberg's avatar
Jody Goldberg committed
745 746 747 748 749 750 751 752 753 754 755 756 757 758 759
			if (r.start.col <= col && col <= r.end.col) {
				row = r.start.row;
				found = TRUE;
			} else if (r.start.col == r.end.col) {
				col = r.start.col;
				row = r.start.row;
				found = TRUE;
			}
		} else if (r.start.col == r.end.col) {
			if (r.start.row <= row && row <= r.end.row) {
				col = r.start.col;
				found = TRUE;
			}
		}
		if (found) {
760
			GnmCell *cell = sheet_cell_get (
Jody Goldberg's avatar
Jody Goldberg committed
761 762 763 764
				eval_sheet (start_sheet, pos->sheet),
				col, row);
			if (cell == NULL)
				return value_new_empty ();
765
			gnm_cell_eval (cell);
766
			return value_dup (cell->value);
Jody Goldberg's avatar
Jody Goldberg committed
767 768 769
		}
	}

770
	return value_new_error_VALUE (pos);
Jody Goldberg's avatar
Jody Goldberg committed
771
}
772

Jody Goldberg's avatar
Jody Goldberg committed
773
static GnmValue *
774 775
bin_arith (GnmExpr const *expr, GnmEvalPos const *ep,
	   GnmValue const *a, GnmValue const *b)
Jody Goldberg's avatar
Jody Goldberg committed
776
{
777 778 779
	gnm_float const va = value_get_as_float (a);
	gnm_float const vb = value_get_as_float (b);
	gnm_float res;
780

781 782 783 784
	switch (GNM_EXPR_GET_OPER (expr)) {
	case GNM_EXPR_OP_ADD:
		res = va + vb;
		break;
785

786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808
	case GNM_EXPR_OP_SUB:
		res = va - vb;
		break;

	case GNM_EXPR_OP_MULT:
		res = va * vb;
		break;

	case GNM_EXPR_OP_DIV:
		if (vb == 0.0)
			return value_new_error_DIV0 (ep);
		res = va / vb;
		break;

	case GNM_EXPR_OP_EXP:
		if ((va == 0 && vb <= 0) || (va < 0 && vb != (int)vb))
			return value_new_error_NUM (ep);

		res = gnm_pow (va, vb);
		break;

	default:
		g_assert_not_reached ();
809
	}
810

811
	if (gnm_finite (res))
812 813 814
		return value_new_float (res);
	else
		return value_new_error_NUM (ep);
Jody Goldberg's avatar
Jody Goldberg committed
815 816
}

Jody Goldberg's avatar
Jody Goldberg committed
817
static GnmValue *
818
bin_cmp (GnmExprOp op, GnmValDiff comp, GnmEvalPos const *ep)
819 820 821 822 823 824 825 826 827 828 829
{
	if (comp == TYPE_MISMATCH) {
		/* TODO TODO TODO : Make error more informative
		 *    regarding what is comparing to what
		 */
		/* For equality comparisons even errors are ok */
		if (op == GNM_EXPR_OP_EQUAL)
			return value_new_bool (FALSE);
		if (op == GNM_EXPR_OP_NOT_EQUAL)
			return value_new_bool (TRUE);

830
		return value_new_error_VALUE (ep);
831 832 833 834 835 836 837
	}

	switch (op) {
	case GNM_EXPR_OP_EQUAL:     return value_new_bool (comp == IS_EQUAL);
	case GNM_EXPR_OP_GT:	    return value_new_bool (comp == IS_GREATER);
	case GNM_EXPR_OP_LT:	    return value_new_bool (comp == IS_LESS);
	case GNM_EXPR_OP_NOT_EQUAL: return value_new_bool (comp != IS_EQUAL);
838
	case GNM_EXPR_OP_LTE:	    return value_new_bool (comp != IS_GREATER);
839 840 841 842 843 844 845
	case GNM_EXPR_OP_GTE:	    return value_new_bool (comp != IS_LESS);

#ifndef DEBUG_SWITCH_ENUM
	default:
		g_assert_not_reached ();
#endif
	}
846
	return value_new_error (ep, _("Internal type error"));
847 848
}

Jody Goldberg's avatar
Jody Goldberg committed
849
static GnmValue *
850 851
cb_bin_cmp (GnmEvalPos const *ep, GnmValue const *a, GnmValue const *b,
	    GnmExpr const *expr)
852
{
Morten Welinder's avatar
Try!  
Morten Welinder committed
853
	if (a != NULL && VALUE_IS_ERROR (a))
854
		return value_dup (a);
Morten Welinder's avatar
Try!  
Morten Welinder committed
855
	if (b != NULL && VALUE_IS_ERROR (b))
856
		return value_dup (b);
857
	return bin_cmp (GNM_EXPR_GET_OPER (expr), value_compare (a, b, FALSE), ep);
858 859 860 861 862 863 864 865
}

static GnmValue *
cb_bin_arith (GnmEvalPos const *ep, GnmValue const *a, GnmValue const *b,
	      GnmExpr const *expr)
{
	GnmValue *res, *va, *vb;

Morten Welinder's avatar
Try!  
Morten Welinder committed
866
	if (a != NULL && VALUE_IS_ERROR (a))
867
		return value_dup (a);
Morten Welinder's avatar
Try!  
Morten Welinder committed
868
	if (b != NULL && VALUE_IS_ERROR (b))
869
		return value_dup (b);
870
	if (VALUE_IS_EMPTY (a))
871
		a = va = (GnmValue *)value_zero;
872
	else if (VALUE_IS_STRING (a)) {
873
		va = format_match_number (value_peek_string (a), NULL,
874 875 876 877 878 879 880
			workbook_date_conv (ep->sheet->workbook));
		if (va == NULL)
			return value_new_error_VALUE (ep);
	} else if (!VALUE_IS_NUMBER (a))
		return value_new_error_VALUE (ep);
	else
		va = (GnmValue *)a;
881
	if (VALUE_IS_EMPTY (b))
882
		b = vb = (GnmValue *)value_zero;
883
	else if (VALUE_IS_STRING (b)) {
884
		vb = format_match_number (value_peek_string (b), NULL,
885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909
			workbook_date_conv (ep->sheet->workbook));
		if (vb == NULL) {
			if (va != a)
				value_release (va);
			return value_new_error_VALUE (ep);
		}
	} else if (!VALUE_IS_NUMBER (b)) {
		if (va != a)
			value_release (va);
		return value_new_error_VALUE (ep);
	} else
		vb = (GnmValue *)b;

	res = bin_arith (expr, ep, va, vb);
	if (va != a)
		value_release (va);
	if (vb != b)
		value_release (vb);
	return res;
}

static GnmValue *
cb_bin_cat (GnmEvalPos const *ep, GnmValue const *a, GnmValue const *b,
	    GnmExpr const *expr)
{
Morten Welinder's avatar
Try!  
Morten Welinder committed
910
	if (a != NULL && VALUE_IS_ERROR (a))
911
		return value_dup (a);
Morten Welinder's avatar
Try!  
Morten Welinder committed
912
	if (b != NULL && VALUE_IS_ERROR (b))
913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932
		return value_dup (b);
	if (a == NULL) {
		if (b != NULL)
			return value_new_string (value_peek_string (b));
		else
			return value_new_string ("");
	} else if (b == NULL)
		return value_new_string (value_peek_string (a));
	else {
		char *tmp = g_strconcat (value_peek_string (a),
					 value_peek_string (b), NULL);
		return value_new_string_nocopy (tmp);
	}
}

typedef GnmValue *(*BinOpImplicitIteratorFunc) (GnmEvalPos const *ep,
						GnmValue const *a,
						GnmValue const *b,
						gpointer user_data);
typedef struct {
Jody Goldberg's avatar
Jody Goldberg committed
933
	GnmEvalPos const *ep;
934 935 936
	GnmValue *res;
	GnmValue const *a, *b;
	BinOpImplicitIteratorFunc	func;
937 938 939

	/* multiply by 0 in unused dimensions.
	 * this is simpler than lots of conditions
940
	 *	state->use_x.a ? x : 0
941 942 943 944
	 **/
	struct {
		int a, b;
	} x, y;
945 946 947 948
	gpointer	user_data;
} BinOpImplicitIteratorState;

static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
949 950
cb_implicit_iter_a_and_b (GnmValueIter const *v_iter,
			  BinOpImplicitIteratorState const *state)
951
{
Jody Goldberg's avatar
Jody Goldberg committed
952 953 954 955 956 957 958 959 960
	state->res->v_array.vals [v_iter->x][v_iter->y] =
		(*state->func) (v_iter->ep,
			value_area_get_x_y (state->a,
				state->x.a * v_iter->x,
				state->y.a * v_iter->y, v_iter->ep),
			value_area_get_x_y (state->b,
				state->x.b * v_iter->x,
				state->y.b * v_iter->y, v_iter->ep),
			state->user_data);
961 962 963
	return NULL;
}
static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
964 965
cb_implicit_iter_a_to_scalar_b (GnmValueIter const *v_iter,
				BinOpImplicitIteratorState const *state)
966
{
Jody Goldberg's avatar
Jody Goldberg committed
967 968 969
	state->res->v_array.vals [v_iter->x][v_iter->y] =
		(*state->func) (v_iter->ep,
			v_iter->v, state->b, state->user_data);
970 971
	return NULL;
}
972 973 974 975 976 977 978 979 980 981

/* This is only triggered if something returns an array or a range which can
 * only happen if we are in array eval mode. */
static GnmValue *
bin_array_iter_a (GnmEvalPos const *ep,
		  GnmValue *a, GnmValue *b,
		  BinOpImplicitIteratorFunc func,
		  GnmExpr const *expr)
{
	BinOpImplicitIteratorState iter_info;
982

983
	/* a must be a cellrange or array, it can not be NULL */
Jody Goldberg's avatar
Jody Goldberg committed
984
	iter_info.ep   = ep;
985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016
	iter_info.func = func;
	iter_info.user_data = (gpointer) expr;
	iter_info.a = a;
	iter_info.b = b;

	/* matrix to matrix
	 * Use matching positions unless the dimension is singular, in which
	 * case use the zero item
	 * res[x][y] = f(a[singular.a.x ? 0 : x, b[singular.b.x ? 0 : x)
	 *
	 * If both items have non-singular sizes for
	 * the same dimension use the min size (see samples/array.xls) */
	if (b != NULL &&
	    (b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY)) {
		int sa, sb, w = 1, h = 1;

		sa = value_area_get_width  (a, ep);
		sb = value_area_get_width  (b, ep);
		if ((iter_info.x.a = (sa == 1) ? 0 : 1))
			w = sa;
		if ((iter_info.x.b = (sb == 1) ? 0 : 1) && (w > sb || w == 1))
			w = sb;

		sa = value_area_get_height  (a, ep);
		sb = value_area_get_height  (b, ep);
		if ((iter_info.y.a = (sa == 1) ? 0 : 1))
			h = sa;
		if ((iter_info.y.b = (sb == 1) ? 0 : 1) && (h > sb || h == 1))
			h = sb;

		iter_info.res = value_new_array_empty (w, h);
		value_area_foreach (iter_info.res, ep, CELL_ITER_ALL,
Jody Goldberg's avatar
Jody Goldberg committed
1017
			(GnmValueIterFunc) cb_implicit_iter_a_and_b, &iter_info);
1018 1019 1020 1021 1022
	} else {
		iter_info.res = value_new_array_empty (
			value_area_get_width  (a, ep),
			value_area_get_height (a, ep));
		value_area_foreach (a, ep, CELL_ITER_ALL,
Jody Goldberg's avatar
Jody Goldberg committed
1023
			(GnmValueIterFunc) cb_implicit_iter_a_to_scalar_b, &iter_info);
1024 1025 1026
	}

	value_release (a);
1027
	value_release (b);
1028 1029 1030
	return iter_info.res;
}

1031
static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
1032 1033
cb_implicit_iter_b_to_scalar_a (GnmValueIter const *v_iter,
				BinOpImplicitIteratorState const *state)
1034
{
Jody Goldberg's avatar
Jody Goldberg committed
1035 1036 1037
	state->res->v_array.vals [v_iter->x][v_iter->y] =
		(*state->func) (v_iter->ep,
			state->a, v_iter->v, state->user_data);
1038 1039 1040
	return NULL;
}
static GnmValue *
1041 1042 1043 1044
bin_array_iter_b (GnmEvalPos const *ep,
		  GnmValue *a, GnmValue *b,
		  BinOpImplicitIteratorFunc func,
		  GnmExpr const *expr)
1045 1046
{
	BinOpImplicitIteratorState iter_info;
1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057

	iter_info.func = func;
	iter_info.user_data = (gpointer) expr;
	iter_info.a = a;
	iter_info.b = b;

	/* b must be a cellrange or array, it can not be NULL */
	iter_info.res = value_new_array_empty (
		value_area_get_width  (b, ep),
		value_area_get_height (b, ep));
	value_area_foreach (b, ep, CELL_ITER_ALL,
Jody Goldberg's avatar
Jody Goldberg committed
1058
		(GnmValueIterFunc) cb_implicit_iter_b_to_scalar_a, &iter_info);
1059
	value_release (a);
1060 1061
	value_release (b);

1062 1063 1064
	return iter_info.res;
}

1065
static GnmValue *
1066
negate_value (GnmValue const *v)
1067
{
1068 1069 1070 1071
	if (VALUE_IS_NUMBER (v)) {
		GnmValue *tmp = value_new_float (0 - value_get_as_float (v));
		value_set_fmt (tmp, VALUE_FMT (v));
		return tmp;
1072
	} else
1073 1074 1075 1076
		return NULL;
}

static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
1077
cb_iter_unary_neg (GnmValueIter const *v_iter, GnmValue *res)
1078
{
Jody Goldberg's avatar
Jody Goldberg committed
1079
	GnmValue const *v = v_iter->v;
1080 1081 1082 1083
	GnmValue *tmp = NULL;

	if (VALUE_IS_EMPTY (v))
		tmp = value_new_int (0);
Morten Welinder's avatar
Try!  
Morten Welinder committed
1084
	else if (VALUE_IS_ERROR (v))
1085
		tmp = value_dup (v);
1086
	else if (VALUE_IS_STRING (v)) {
Jody Goldberg's avatar
Jody Goldberg committed
1087 1088 1089
		GnmValue *conv = format_match_number (
			value_peek_string (v), NULL,
			workbook_date_conv (v_iter->ep->sheet->workbook));
1090 1091 1092 1093
		if (conv != NULL) {
			tmp = negate_value (conv);
			value_release (conv);
		}
1094 1095
	} else {
		/* BOOL goes here.  */
1096
		tmp = negate_value (v);
1097
	}
1098

Jody Goldberg's avatar
Jody Goldberg committed
1099 1100 1101
	if (NULL == tmp)
		tmp = value_new_error_VALUE (v_iter->ep);
	res->v_array.vals[v_iter->x][v_iter->y] = tmp;
1102 1103 1104 1105
	return NULL;
}

static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
1106
cb_iter_percentage (GnmValueIter const *v_iter, GnmValue *res)
1107
{
Jody Goldberg's avatar
Jody Goldberg committed
1108
	GnmValue const *v = v_iter->v;
1109
	GnmValue *tmp;
1110 1111 1112

	if (VALUE_IS_EMPTY (v))
		tmp = value_new_int (0);
Morten Welinder's avatar
Try!  
Morten Welinder committed
1113
	else if (VALUE_IS_ERROR (v))
1114
		tmp = value_dup (v);
1115 1116
	else {
		GnmValue *conv = NULL;
1117
		if (VALUE_IS_STRING (v)) {
Jody Goldberg's avatar
Jody Goldberg committed
1118 1119 1120
			conv = format_match_number (
				value_peek_string (v), NULL,
				workbook_date_conv (v_iter->