expr.c 80.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"
Jody Goldberg's avatar
Jody Goldberg committed
39
#include "workbook-priv.h"
Jeffrey Stedfast's avatar
Jeffrey Stedfast committed
40
#include "gutils.h"
41
#include "parse-util.h"
42
#include "mathfunc.h"
43

Jody Goldberg's avatar
Jody Goldberg committed
44
#include <go-string.h>
45
#include <goffice/utils/go-locale.h>
46
#include <goffice/utils/go-format.h>
Morten Welinder's avatar
Morten Welinder committed
47
#include <goffice/utils/go-glib-extras.h>
Jody Goldberg's avatar
Jody Goldberg committed
48 49 50
#include <math.h>
#include <string.h>
#include <stdlib.h>
51

52 53 54 55 56 57 58 59 60
/*
 * 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
61 62
/* Memory pools for expressions.  */
static GOMemChunk *expression_pool_small, *expression_pool_big;
63 64
#define CHUNK_ALLOC(T,p) ((T*)go_mem_chunk_alloc (p))
#define CHUNK_FREE(p,v) go_mem_chunk_free ((p), (v))
65 66 67 68 69
#else
#define CHUNK_ALLOC(T,c) g_new (T,1)
#define CHUNK_FREE(p,v) g_free ((v))
#endif

70 71
/***************************************************************************/

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

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

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

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

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

99
	ans = CHUNK_ALLOC (GnmExprFunction, expression_pool_small);
100

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

107
	return (GnmExpr *)ans;
108
}
109

110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
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
125 126 127 128
GnmExpr const *
gnm_expr_new_funcall1 (GnmFunc *func,
		       GnmExpr const *arg0)
{
129 130 131
	GnmExprConstPtr *argv = g_new (GnmExprConstPtr, 1);
	argv[0] = arg0;
	return gnm_expr_new_funcallv (func, 1, argv);
Morten Welinder's avatar
Morten Welinder committed
132 133 134 135 136 137 138
}

GnmExpr const *
gnm_expr_new_funcall2 (GnmFunc *func,
		       GnmExpr const *arg0,
		       GnmExpr const *arg1)
{
139 140 141 142
	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
143 144 145 146 147 148 149 150
}

GnmExpr const *
gnm_expr_new_funcall3 (GnmFunc *func,
		       GnmExpr const *arg0,
		       GnmExpr const *arg1,
		       GnmExpr const *arg2)
{
151 152 153 154 155
	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
156 157
}

158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
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);
}

173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
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
190

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

262
	return (GnmExpr *)ans;
263 264
}

Jody Goldberg's avatar
Jody Goldberg committed
265 266 267
/***************************************************************************/

/**
268
 * gnm_expr_new_array_corner :
Jody Goldberg's avatar
Jody Goldberg committed
269 270 271 272 273 274
 * @cols :
 * @rows :
 * @expr : optionally NULL.
 *
 * Absorb a referernce to @expr if it is non NULL.
 **/
275
static GnmExpr const *
276
gnm_expr_new_array_corner(int cols, int rows, GnmExpr const *expr)
277
{
278
	GnmExprArrayCorner *ans;
279

280
	ans = CHUNK_ALLOC (GnmExprArrayCorner, expression_pool_big);
281 282
	if (ans == NULL)
		return NULL;
283

284
	ans->oper = GNM_EXPR_OP_ARRAY_CORNER;
285 286
	ans->rows = rows;
	ans->cols = cols;
287 288 289 290 291
	ans->value = NULL;
	ans->expr = expr;
	return (GnmExpr *)ans;
}

292
static GnmExpr const *
293 294 295 296
gnm_expr_new_array_elem  (int x, int y)
{
	GnmExprArrayElem *ans;

297
	ans = CHUNK_ALLOC (GnmExprArrayElem, expression_pool_small);
298 299 300
	if (ans == NULL)
		return NULL;

301
	ans->oper = GNM_EXPR_OP_ARRAY_ELEM;
302 303
	ans->x = x;
	ans->y = y;
304
	return (GnmExpr *)ans;
305 306
}

Jody Goldberg's avatar
Jody Goldberg committed
307 308
/***************************************************************************/

309 310
static GnmExpr const *
gnm_expr_new_setv (int argc, GnmExprConstPtr *argv)
Jody Goldberg's avatar
Jody Goldberg committed
311
{
312 313
	GnmExprSet *ans = CHUNK_ALLOC (GnmExprSet, expression_pool_small);

314
	ans->oper = GNM_EXPR_OP_SET;
315 316 317 318
	ans->argc = argc;
	ans->argv = argv;

	return (GnmExpr *)ans;
Jody Goldberg's avatar
Jody Goldberg committed
319 320
}

321 322
GnmExpr const *
gnm_expr_new_set (GnmExprList *set)
323
{
324 325 326
	int i, argc;
	GnmExprConstPtr *argv;
	GnmExprList *set0 = set;
327

328 329 330 331 332
	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);
333

334
	return gnm_expr_new_setv (argc, argv);
335 336
}

Jody Goldberg's avatar
Jody Goldberg committed
337
/***************************************************************************/
338 339 340 341 342 343 344

/**
 * 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
345
 * but equivalent, if the arguments allow it.
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
 *
 * 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
372

373 374
GnmExpr const *
gnm_expr_copy (GnmExpr const *expr)
375
{
376 377
	g_return_val_if_fail (expr != NULL, NULL);

378 379 380 381 382 383 384 385
	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));
386

387 388 389 390
	case GNM_EXPR_OP_ANY_UNARY:
		return gnm_expr_new_unary
			(GNM_EXPR_GET_OPER (expr),
			 gnm_expr_copy (expr->unary.value));
391

392 393 394 395
	case GNM_EXPR_OP_FUNCALL: {
		GnmExprConstPtr *argv =
			g_new (GnmExprConstPtr, expr->func.argc);
		int i;
Arturo Espinosa's avatar
Arturo Espinosa committed
396

397 398
		for (i = 0; i < expr->func.argc; i++)
			argv[i] = gnm_expr_copy (expr->func.argv[i]);
399

400 401 402 403 404
		return gnm_expr_new_funcallv
			(expr->func.func,
			 expr->func.argc,
			 argv);
	}
405

406 407 408 409 410 411 412 413 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
	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
457

458
	switch (GNM_EXPR_GET_OPER (expr)) {
459
	case GNM_EXPR_OP_RANGE_CTOR:
460
	case GNM_EXPR_OP_INTERSECT:
461
	case GNM_EXPR_OP_ANY_BINARY:
462 463
		gnm_expr_free (expr->binary.value_a);
		gnm_expr_free (expr->binary.value_b);
464
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
Arturo Espinosa's avatar
Arturo Espinosa committed
465
		break;
466

467 468 469 470
	case GNM_EXPR_OP_FUNCALL: {
		int i;

		for (i = 0; i < expr->func.argc; i++)
471
			gnm_expr_free (expr->func.argv[i]);
Morten Welinder's avatar
Morten Welinder committed
472
		g_free (expr->func.argv);
Jody Goldberg's avatar
Jody Goldberg committed
473
		gnm_func_unref (expr->func.func);
474
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
Arturo Espinosa's avatar
Arturo Espinosa committed
475
		break;
476
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
477

478
	case GNM_EXPR_OP_NAME:
479
		expr_name_unref (expr->name.name);
480
		CHUNK_FREE (expression_pool_big, (gpointer)expr);
Michael Meeks's avatar
Michael Meeks committed
481 482
		break;

483
	case GNM_EXPR_OP_CONSTANT:
Jody Goldberg's avatar
Jody Goldberg committed
484
		value_release ((GnmValue *)expr->constant.value);
485
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
486 487 488
		break;

	case GNM_EXPR_OP_CELLREF:
489
		CHUNK_FREE (expression_pool_big, (gpointer)expr);
Arturo Espinosa's avatar
Arturo Espinosa committed
490 491
		break;

492
	case GNM_EXPR_OP_ANY_UNARY:
493
		gnm_expr_free (expr->unary.value);
494
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
Arturo Espinosa's avatar
Arturo Espinosa committed
495
		break;
496

497 498 499
	case GNM_EXPR_OP_ARRAY_CORNER:
		if (expr->array_corner.value)
			value_release (expr->array_corner.value);
500
		gnm_expr_free (expr->array_corner.expr);
501
		CHUNK_FREE (expression_pool_big, (gpointer)expr);
502 503 504
		break;

	case GNM_EXPR_OP_ARRAY_ELEM:
505
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
Jody Goldberg's avatar
Jody Goldberg committed
506
		break;
507

508 509 510 511
	case GNM_EXPR_OP_SET: {
		int i;

		for (i = 0; i < expr->set.argc; i++)
512
			gnm_expr_free (expr->set.argv[i]);
Morten Welinder's avatar
Morten Welinder committed
513
		g_free (expr->set.argv);
514
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
515
		break;
516
	}
517 518

#ifndef DEBUG_SWITCH_ENUM
519
	default:
520
		g_assert_not_reached ();
521
		break;
522
#endif
Arturo Espinosa's avatar
Arturo Espinosa committed
523
	}
524 525
}

Jody Goldberg's avatar
Jody Goldberg committed
526
/**
527
 * gnm_expr_equal : Returns TRUE if the supplied expressions are exactly the
Jody Goldberg's avatar
Jody Goldberg committed
528
 *   same.  No eval position is used to see if they are effectively the same.
Morten Welinder's avatar
Morten Welinder committed
529
 *   Named expressions must refer the same name, having equivalent names is
Jody Goldberg's avatar
Jody Goldberg committed
530 531
 *   insufficeient.
 */
532
static gboolean
533
gnm_expr_equal (GnmExpr const *a, GnmExpr const *b)
Jody Goldberg's avatar
Jody Goldberg committed
534 535 536 537 538 539 540
{
	if (a == b)
		return TRUE;

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

541
	if (GNM_EXPR_GET_OPER (a) != GNM_EXPR_GET_OPER (b))
Jody Goldberg's avatar
Jody Goldberg committed
542 543
		return FALSE;

544
	switch (GNM_EXPR_GET_OPER (a)) {
545
	case GNM_EXPR_OP_RANGE_CTOR:
546
	case GNM_EXPR_OP_INTERSECT:
547 548 549
	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
550

551 552
	case GNM_EXPR_OP_ANY_UNARY:
		return gnm_expr_equal (a->unary.value, b->unary.value);
Jody Goldberg's avatar
Jody Goldberg committed
553

554 555 556 557 558 559 560 561 562 563 564 565
	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
566

567
	case GNM_EXPR_OP_NAME:
568 569 570
		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
571

572
	case GNM_EXPR_OP_CELLREF:
573
		return gnm_cellref_equal (&a->cellref.ref, &b->cellref.ref);
Jody Goldberg's avatar
Jody Goldberg committed
574

575 576
	case GNM_EXPR_OP_CONSTANT:
		return value_equal (a->constant.value, b->constant.value);
Jody Goldberg's avatar
Jody Goldberg committed
577

578 579 580
	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
581 582 583

		return	aa->cols == ab->cols &&
			aa->rows == ab->rows &&
584 585 586 587 588 589
			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
590 591
	}

592 593 594 595 596 597 598 599 600 601 602
	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
603 604 605 606 607
	}

	return FALSE;
}

608
static GnmCell *
609 610
array_elem_get_corner (GnmExprArrayElem const *elem,
		       Sheet const *sheet, GnmCellPos const *pos)
611
{
612
	GnmCell *corner = sheet_cell_get (sheet,
613
		pos->col - elem->x, pos->row - elem->y);
614 615 616

	/* Sanity check incase the corner gets removed for some reason */
	g_return_val_if_fail (corner != NULL, NULL);
617
	g_return_val_if_fail (gnm_cell_has_expr (corner), NULL);
618 619
	g_return_val_if_fail (corner->base.texpr != (void *)0xdeadbeef, NULL);
	g_return_val_if_fail (IS_GNM_EXPR_TOP (corner->base.texpr), NULL);
620 621 622 623 624

	return corner;
}

static gboolean
Jody Goldberg's avatar
Jody Goldberg committed
625
gnm_expr_extract_ref (GnmRangeRef *res, GnmExpr const *expr,
Morten Welinder's avatar
Morten Welinder committed
626
		      GnmEvalPos const *pos, GnmExprEvalFlags flags)
627
{
628
	switch (GNM_EXPR_GET_OPER (expr)) {
629 630
	case GNM_EXPR_OP_FUNCALL : {
		gboolean failed = TRUE;
Jody Goldberg's avatar
Jody Goldberg committed
631
		GnmValue *v;
632
		GnmFuncEvalInfo ei;
633

634
		ei.pos = pos;
635
		ei.func_call = &expr->func;
636
		v = function_call_with_exprs (&ei, flags);
637 638

		if (v != NULL) {
Jody Goldberg's avatar
Jody Goldberg committed
639 640
			if (v->type == VALUE_CELLRANGE) {
				*res = v->v_range.cell;
641 642 643 644 645 646 647 648
				failed = FALSE;
			}
			value_release (v);
		}
		return failed;
	}

	case GNM_EXPR_OP_CELLREF :
Jody Goldberg's avatar
Jody Goldberg committed
649 650
		res->a = expr->cellref.ref;
		res->b = expr->cellref.ref;
651 652 653
		return FALSE;

	case GNM_EXPR_OP_CONSTANT: {
Jody Goldberg's avatar
Jody Goldberg committed
654
		GnmValue const *v = expr->constant.value;
Jody Goldberg's avatar
Jody Goldberg committed
655 656
		if (v->type == VALUE_CELLRANGE) {
			*res = v->v_range.cell;
657 658 659 660 661 662
			return FALSE;
		}
		return TRUE;
	}

	case GNM_EXPR_OP_NAME:
663
		if (!expr->name.name->active)
664
			return TRUE;
665 666
		return gnm_expr_extract_ref (res, expr->name.name->texpr->expr,
					     pos, flags);
667 668 669 670 671 672
	default :
		break;
	}
	return TRUE;
}

Jody Goldberg's avatar
Jody Goldberg committed
673 674
static inline GnmValue *
handle_empty (GnmValue *res, GnmExprEvalFlags flags)
675 676 677 678 679
{
	if (res == NULL)
		return (flags & GNM_EXPR_EVAL_PERMIT_EMPTY)
		    ? NULL : value_new_int (0);

680
	if (VALUE_IS_EMPTY (res)) {
681 682 683 684 685 686 687
		value_release (res);
		return (flags & GNM_EXPR_EVAL_PERMIT_EMPTY)
		    ? NULL : value_new_int (0);
	}
	return res;
}

Jody Goldberg's avatar
Jody Goldberg committed
688 689
/**
 * value_intersection :
690
 * @v   : a VALUE_CELLRANGE or VALUE_ARRAY
Morten Welinder's avatar
Morten Welinder committed
691
 * @pos :
Jody Goldberg's avatar
Jody Goldberg committed
692 693 694 695 696 697 698 699 700 701 702 703 704 705 706
 *
 * 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
707
static GnmValue *
Morten Welinder's avatar
Morten Welinder committed
708
value_intersection (GnmValue *v, GnmEvalPos const *pos)
Jody Goldberg's avatar
Jody Goldberg committed
709
{
Jody Goldberg's avatar
Jody Goldberg committed
710 711
	GnmValue *res = NULL;
	GnmRange r;
Jody Goldberg's avatar
Jody Goldberg committed
712 713 714 715
	Sheet *start_sheet, *end_sheet;
	gboolean found = FALSE;

	if (v->type == VALUE_ARRAY) {
716 717 718
		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
719 720 721 722 723
		value_release (v);
		return res;
	}

	/* inverted ranges */
724
	gnm_rangeref_normalize (&v->v_range.cell, pos, &start_sheet, &end_sheet, &r);
Jody Goldberg's avatar
Jody Goldberg committed
725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746
	value_release (v);

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

		if (r.start.row == r.end.row) {
			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) {
747
			GnmCell *cell = sheet_cell_get (
Jody Goldberg's avatar
Jody Goldberg committed
748 749 750 751
				eval_sheet (start_sheet, pos->sheet),
				col, row);
			if (cell == NULL)
				return value_new_empty ();
752
			gnm_cell_eval (cell);
753
			return value_dup (cell->value);
Jody Goldberg's avatar
Jody Goldberg committed
754 755 756
		}
	}

757
	return value_new_error_VALUE (pos);
Jody Goldberg's avatar
Jody Goldberg committed
758
}
759

Jody Goldberg's avatar
Jody Goldberg committed
760
static GnmValue *
761 762
bin_arith (GnmExpr const *expr, GnmEvalPos const *ep,
	   GnmValue const *a, GnmValue const *b)
Jody Goldberg's avatar
Jody Goldberg committed
763
{
764 765 766
	gnm_float const va = value_get_as_float (a);
	gnm_float const vb = value_get_as_float (b);
	gnm_float res;
767

768 769 770 771
	switch (GNM_EXPR_GET_OPER (expr)) {
	case GNM_EXPR_OP_ADD:
		res = va + vb;
		break;
772

773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795
	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 ();
796
	}
797

798
	if (gnm_finite (res))
799 800 801
		return value_new_float (res);
	else
		return value_new_error_NUM (ep);
Jody Goldberg's avatar
Jody Goldberg committed
802 803
}

Jody Goldberg's avatar
Jody Goldberg committed
804
static GnmValue *
805
bin_cmp (GnmExprOp op, GnmValDiff comp, GnmEvalPos const *ep)
806 807 808 809 810 811 812 813 814 815 816
{
	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);

817
		return value_new_error_VALUE (ep);
818 819 820 821 822 823 824
	}

	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);
825
	case GNM_EXPR_OP_LTE:	    return value_new_bool (comp != IS_GREATER);
826 827 828 829 830 831 832
	case GNM_EXPR_OP_GTE:	    return value_new_bool (comp != IS_LESS);

#ifndef DEBUG_SWITCH_ENUM
	default:
		g_assert_not_reached ();
#endif
	}
833
	return value_new_error (ep, _("Internal type error"));
834 835
}

Jody Goldberg's avatar
Jody Goldberg committed
836
static GnmValue *
837 838
cb_bin_cmp (GnmEvalPos const *ep, GnmValue const *a, GnmValue const *b,
	    GnmExpr const *expr)
839
{
Morten Welinder's avatar
Try!  
Morten Welinder committed
840
	if (a != NULL && VALUE_IS_ERROR (a))
841
		return value_dup (a);
Morten Welinder's avatar
Try!  
Morten Welinder committed
842
	if (b != NULL && VALUE_IS_ERROR (b))
843
		return value_dup (b);
844
	return bin_cmp (GNM_EXPR_GET_OPER (expr), value_compare (a, b, FALSE), ep);
845 846 847 848 849 850 851 852
}

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
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);
Jody Goldberg's avatar
Jody Goldberg committed
857
	if (VALUE_IS_EMPTY (a))
858
		a = va = (GnmValue *)value_zero;
859
	else if (VALUE_IS_STRING (a)) {
860
		va = format_match_number (value_peek_string (a), NULL,
861 862 863 864 865 866 867
			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;
Jody Goldberg's avatar
Jody Goldberg committed
868
	if (VALUE_IS_EMPTY (b))
869
		b = vb = (GnmValue *)value_zero;
870
	else if (VALUE_IS_STRING (b)) {
871
		vb = format_match_number (value_peek_string (b), NULL,
872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896
			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
897
	if (a != NULL && VALUE_IS_ERROR (a))
898
		return value_dup (a);
Morten Welinder's avatar
Try!  
Morten Welinder committed
899
	if (b != NULL && VALUE_IS_ERROR (b))
900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919
		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
920
	GnmEvalPos const *ep;
921 922 923
	GnmValue *res;
	GnmValue const *a, *b;
	BinOpImplicitIteratorFunc	func;
924 925 926

	/* multiply by 0 in unused dimensions.
	 * this is simpler than lots of conditions
927
	 *	state->use_x.a ? x : 0
928 929 930 931
	 **/
	struct {
		int a, b;
	} x, y;
932 933 934 935
	gpointer	user_data;
} BinOpImplicitIteratorState;

static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
936 937
cb_implicit_iter_a_and_b (GnmValueIter const *v_iter,
			  BinOpImplicitIteratorState const *state)
938
{
Jody Goldberg's avatar
Jody Goldberg committed
939 940 941 942 943 944 945 946 947
	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);
948 949 950
	return NULL;
}
static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
951 952
cb_implicit_iter_a_to_scalar_b (GnmValueIter const *v_iter,
				BinOpImplicitIteratorState const *state)
953
{
Jody Goldberg's avatar
Jody Goldberg committed
954 955 956
	state->res->v_array.vals [v_iter->x][v_iter->y] =
		(*state->func) (v_iter->ep,
			v_iter->v, state->b, state->user_data);
957 958
	return NULL;
}
959 960 961 962 963 964 965 966 967 968

/* 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;
969

970
	/* a must be a cellrange or array, it can not be NULL */
Jody Goldberg's avatar
Jody Goldberg committed
971
	iter_info.ep   = ep;
972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003
	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
1004
			(GnmValueIterFunc) cb_implicit_iter_a_and_b, &iter_info);
1005 1006 1007 1008 1009
	} 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
1010
			(GnmValueIterFunc) cb_implicit_iter_a_to_scalar_b, &iter_info);
1011 1012 1013 1014 1015 1016 1017 1018
	}

	value_release (a);
	if (b != NULL)
		value_release (b);
	return iter_info.res;
}

1019
static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
1020 1021
cb_implicit_iter_b_to_scalar_a (GnmValueIter const *v_iter,
				BinOpImplicitIteratorState const *state)
1022
{
Jody Goldberg's avatar
Jody Goldberg committed
1023 1024 1025
	state->res->v_array.vals [v_iter->x][v_iter->y] =
		(*state->func) (v_iter->ep,
			state->a, v_iter->v, state->user_data);
1026 1027 1028
	return NULL;
}
static GnmValue *
1029 1030 1031 1032
bin_array_iter_b (GnmEvalPos const *ep,
		  GnmValue *a, GnmValue *b,
		  BinOpImplicitIteratorFunc func,
		  GnmExpr const *expr)
1033 1034
{
	BinOpImplicitIteratorState iter_info;
1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045

	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
1046
		(GnmValueIterFunc) cb_implicit_iter_b_to_scalar_a, &iter_info);
1047 1048
	if (a != NULL)
		value_release (a);
1049 1050
	value_release (b);

1051 1052 1053
	return iter_info.res;
}

1054
static GnmValue *
1055
negate_value (GnmValue const *v)
1056
{
1057 1058 1059 1060
	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;
1061
	} else
1062 1063 1064 1065
		return NULL;
}

static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
1066
cb_iter_unary_neg (GnmValueIter const *v_iter, GnmValue *res)
1067
{
Jody Goldberg's avatar
Jody Goldberg committed
1068
	GnmValue const *v = v_iter->v;
1069 1070 1071 1072
	GnmValue *tmp = NULL;

	if (VALUE_IS_EMPTY (v))
		tmp = value_new_int (0);
Morten Welinder's avatar
Try!  
Morten Welinder committed
1073
	else if (VALUE_IS_ERROR (v))
1074
		tmp = value_dup (v);
1075
	else if (VALUE_IS_STRING (v)) {
Jody Goldberg's avatar
Jody Goldberg committed
1076 1077 1078
		GnmValue *conv = format_match_number (
			value_peek_string (v), NULL,
			workbook_date_conv (v_iter->ep->sheet->workbook));
1079 1080 1081 1082
		if (conv != NULL) {
			tmp = negate_value (conv);
			value_release (conv);
		}
1083 1084
	} else {
		/* BOOL goes here.  */
1085
		tmp = negate_value (v);
1086
	}
1087

Jody Goldberg's avatar
Jody Goldberg committed
1088 1089 1090
	if (NULL == tmp)
		tmp = value_new_error_VALUE (v_iter->ep);
	res->v_array.vals[v_iter->x][v_iter->y] = tmp;
1091 1092 1093 1094
	return NULL;
}

static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
1095
cb_iter_percentage (GnmValueIter const *v_iter, GnmValue *res)
1096
{
Jody Goldberg's avatar
Jody Goldberg committed
1097
	GnmValue const *v = v_iter->v;
1098
	GnmValue *tmp;
1099 1100 1101

	if (VALUE_IS_EMPTY (v))
		tmp = value_new_int (0);
Morten Welinder's avatar
Try!  
Morten Welinder committed
1102
	else if (VALUE_IS_ERROR (v))
1103
		tmp = value_dup (v);
1104 1105
	else {
		GnmValue *conv = NULL;
1106
		if (VALUE_IS_STRING (v)) {
Jody Goldberg's avatar
Jody Goldberg committed
1107 1108 1109
			conv = format_match_number (
				value_peek_string (v), NULL,
				workbook_date_conv (v_iter->ep->sheet->workbook));
1110 1111 1112 1113 1114 1115
			if (conv != NULL)
				v = conv;
		}

		if (VALUE_IS_NUMBER (v)){
			tmp = value_new_float (value_get_as_float (v) / 100);
1116
			value_set_fmt (tmp, go_format_default_percentage ());
1117
		} else
Jody Goldberg's avatar
Jody Goldberg committed
1118
			tmp = value_new_error_VALUE (v_iter->ep);
1119