expr.c 79.4 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)
7 8 9 10 11 12 13 14 15 16 17 18
 *
 * 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
19
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
20
 * USA
Miguel de Icaza's avatar
Miguel de Icaza committed
21
 */
22
#include <gnumeric-config.h>
23
#include <glib/gi18n-lib.h>
24
#include "gnumeric.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
25
#include "expr.h"
26

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

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

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

68 69
/***************************************************************************/

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

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

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

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

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

97
	ans = CHUNK_ALLOC (GnmExprFunction, expression_pool_small);
98

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

105
	return (GnmExpr *)ans;
106
}
107

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

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

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

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

Morten Welinder's avatar
Morten Welinder committed
171

Jody Goldberg's avatar
Jody Goldberg committed
172 173
/***************************************************************************/

174 175
GnmExpr const *
gnm_expr_new_unary  (GnmExprOp op, GnmExpr const *e)
Morten Welinder's avatar
Morten Welinder committed
176
{
177
	GnmExprUnary *ans;
Morten Welinder's avatar
Morten Welinder committed
178

179
	ans = CHUNK_ALLOC (GnmExprUnary, expression_pool_small);
180 181 182
	if (!ans)
		return NULL;

183
	ans->oper = op;
184
	ans->value = e;
185

186
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
187 188
}

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

191 192
GnmExpr const *
gnm_expr_new_binary (GnmExpr const *l, GnmExprOp op, GnmExpr const *r)
Morten Welinder's avatar
Morten Welinder committed
193
{
194
	GnmExprBinary *ans;
Morten Welinder's avatar
Morten Welinder committed
195

196
	ans = CHUNK_ALLOC (GnmExprBinary, expression_pool_small);
197 198
	if (!ans)
		return NULL;
199

200
	ans->oper = op;
201 202
	ans->value_a = l;
	ans->value_b = r;
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_name (GnmNamedExpr *name,
211
		   Sheet *optional_scope, Workbook *optional_wb_scope)
Morten Welinder's avatar
Morten Welinder committed
212
{
213
	GnmExprName *ans;
Morten Welinder's avatar
Morten Welinder committed
214

215
	ans = CHUNK_ALLOC (GnmExprName, expression_pool_big);
216 217
	if (!ans)
		return NULL;
218

219
	ans->oper = GNM_EXPR_OP_NAME;
220
	ans->name = name;
221
	expr_name_ref (name);
222

223 224 225
	ans->optional_scope = optional_scope;
	ans->optional_wb_scope = optional_wb_scope;

226
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
227
}
228

Jody Goldberg's avatar
Jody Goldberg committed
229 230
/***************************************************************************/

231
GnmExpr const *
Jody Goldberg's avatar
Jody Goldberg committed
232
gnm_expr_new_cellref (GnmCellRef const *cr)
233
{
234
	GnmExprCellRef *ans;
235

236
	ans = CHUNK_ALLOC (GnmExprCellRef, expression_pool_big);
237 238
	if (!ans)
		return NULL;
239

240
	ans->oper = GNM_EXPR_OP_CELLREF;
241 242
	ans->ref = *cr;

243
	return (GnmExpr *)ans;
244 245
}

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

/**
249
 * gnm_expr_new_array_corner :
Jody Goldberg's avatar
Jody Goldberg committed
250 251 252 253 254 255
 * @cols :
 * @rows :
 * @expr : optionally NULL.
 *
 * Absorb a referernce to @expr if it is non NULL.
 **/
256
static GnmExpr const *
257
gnm_expr_new_array_corner(int cols, int rows, GnmExpr const *expr)
258
{
259
	GnmExprArrayCorner *ans;
260

261
	ans = CHUNK_ALLOC (GnmExprArrayCorner, expression_pool_big);
262 263
	if (ans == NULL)
		return NULL;
264

265
	ans->oper = GNM_EXPR_OP_ARRAY_CORNER;
266 267
	ans->rows = rows;
	ans->cols = cols;
268 269 270 271 272
	ans->value = NULL;
	ans->expr = expr;
	return (GnmExpr *)ans;
}

273
static GnmExpr const *
274 275 276 277
gnm_expr_new_array_elem  (int x, int y)
{
	GnmExprArrayElem *ans;

278
	ans = CHUNK_ALLOC (GnmExprArrayElem, expression_pool_small);
279 280 281
	if (ans == NULL)
		return NULL;

282
	ans->oper = GNM_EXPR_OP_ARRAY_ELEM;
283 284
	ans->x = x;
	ans->y = y;
285
	return (GnmExpr *)ans;
286 287
}

Jody Goldberg's avatar
Jody Goldberg committed
288 289
/***************************************************************************/

290 291
static GnmExpr const *
gnm_expr_new_setv (int argc, GnmExprConstPtr *argv)
Jody Goldberg's avatar
Jody Goldberg committed
292
{
293 294
	GnmExprSet *ans = CHUNK_ALLOC (GnmExprSet, expression_pool_small);

295
	ans->oper = GNM_EXPR_OP_SET;
296 297 298 299
	ans->argc = argc;
	ans->argv = argv;

	return (GnmExpr *)ans;
Jody Goldberg's avatar
Jody Goldberg committed
300 301
}

302 303
GnmExpr const *
gnm_expr_new_set (GnmExprList *set)
304
{
305 306 307
	int i, argc;
	GnmExprConstPtr *argv;
	GnmExprList *set0 = set;
308

309 310 311 312 313
	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);
314

315
	return gnm_expr_new_setv (argc, argv);
316 317
}

Jody Goldberg's avatar
Jody Goldberg committed
318
/***************************************************************************/
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352

/**
 * gnm_expr_new_range_ctor:
 * @l: start range
 * @r: end range
 *
 * This function builds a range constructor or something simpler,
 * but equivalent, if the arguments allow it. 
 *
 * 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
353

354 355
GnmExpr const *
gnm_expr_copy (GnmExpr const *expr)
356
{
357 358
	g_return_val_if_fail (expr != NULL, NULL);

359 360 361 362 363 364 365 366
	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));
367

368 369 370 371
	case GNM_EXPR_OP_ANY_UNARY:
		return gnm_expr_new_unary
			(GNM_EXPR_GET_OPER (expr),
			 gnm_expr_copy (expr->unary.value));
372

373 374 375 376
	case GNM_EXPR_OP_FUNCALL: {
		GnmExprConstPtr *argv =
			g_new (GnmExprConstPtr, expr->func.argc);
		int i;
Arturo Espinosa's avatar
Arturo Espinosa committed
377

378 379
		for (i = 0; i < expr->func.argc; i++)
			argv[i] = gnm_expr_copy (expr->func.argv[i]);
380

381 382 383 384 385
		return gnm_expr_new_funcallv
			(expr->func.func,
			 expr->func.argc,
			 argv);
	}
386

387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 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
	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
438

439
	switch (GNM_EXPR_GET_OPER (expr)) {
440
	case GNM_EXPR_OP_RANGE_CTOR:
441
	case GNM_EXPR_OP_INTERSECT:
442
	case GNM_EXPR_OP_ANY_BINARY:
443 444
		gnm_expr_free (expr->binary.value_a);
		gnm_expr_free (expr->binary.value_b);
445
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
Arturo Espinosa's avatar
Arturo Espinosa committed
446
		break;
447

448 449 450 451
	case GNM_EXPR_OP_FUNCALL: {
		int i;

		for (i = 0; i < expr->func.argc; i++)
452
			gnm_expr_free (expr->func.argv[i]);
Morten Welinder's avatar
Morten Welinder committed
453
		g_free (expr->func.argv);
Jody Goldberg's avatar
Jody Goldberg committed
454
		gnm_func_unref (expr->func.func);
455
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
Arturo Espinosa's avatar
Arturo Espinosa committed
456
		break;
457
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
458

459
	case GNM_EXPR_OP_NAME:
460
		expr_name_unref (expr->name.name);
461
		CHUNK_FREE (expression_pool_big, (gpointer)expr);
Michael Meeks's avatar
Michael Meeks committed
462 463
		break;

464
	case GNM_EXPR_OP_CONSTANT:
Jody Goldberg's avatar
Jody Goldberg committed
465
		value_release ((GnmValue *)expr->constant.value);
466
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
467 468 469
		break;

	case GNM_EXPR_OP_CELLREF:
470
		CHUNK_FREE (expression_pool_big, (gpointer)expr);
Arturo Espinosa's avatar
Arturo Espinosa committed
471 472
		break;

473
	case GNM_EXPR_OP_ANY_UNARY:
474
		gnm_expr_free (expr->unary.value);
475
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
Arturo Espinosa's avatar
Arturo Espinosa committed
476
		break;
477

478 479 480
	case GNM_EXPR_OP_ARRAY_CORNER:
		if (expr->array_corner.value)
			value_release (expr->array_corner.value);
481
		gnm_expr_free (expr->array_corner.expr);
482
		CHUNK_FREE (expression_pool_big, (gpointer)expr);
483 484 485
		break;

	case GNM_EXPR_OP_ARRAY_ELEM:
486
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
Jody Goldberg's avatar
Jody Goldberg committed
487
		break;
488

489 490 491 492
	case GNM_EXPR_OP_SET: {
		int i;

		for (i = 0; i < expr->set.argc; i++)
493
			gnm_expr_free (expr->set.argv[i]);
Morten Welinder's avatar
Morten Welinder committed
494
		g_free (expr->set.argv);
495
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
496
		break;
497
	}
498 499

#ifndef DEBUG_SWITCH_ENUM
500
	default:
501
		g_assert_not_reached ();
502
		break;
503
#endif
Arturo Espinosa's avatar
Arturo Espinosa committed
504
	}
505 506
}

Jody Goldberg's avatar
Jody Goldberg committed
507
/**
508
 * gnm_expr_equal : Returns TRUE if the supplied expressions are exactly the
Jody Goldberg's avatar
Jody Goldberg committed
509
 *   same.  No eval position is used to see if they are effectively the same.
Morten Welinder's avatar
Morten Welinder committed
510
 *   Named expressions must refer the same name, having equivalent names is
Jody Goldberg's avatar
Jody Goldberg committed
511 512
 *   insufficeient.
 */
513
static gboolean
514
gnm_expr_equal (GnmExpr const *a, GnmExpr const *b)
Jody Goldberg's avatar
Jody Goldberg committed
515 516 517 518 519 520 521
{
	if (a == b)
		return TRUE;

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

522
	if (GNM_EXPR_GET_OPER (a) != GNM_EXPR_GET_OPER (b))
Jody Goldberg's avatar
Jody Goldberg committed
523 524
		return FALSE;

525
	switch (GNM_EXPR_GET_OPER (a)) {
526
	case GNM_EXPR_OP_RANGE_CTOR:
527
	case GNM_EXPR_OP_INTERSECT:
528 529 530
	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
531

532 533
	case GNM_EXPR_OP_ANY_UNARY:
		return gnm_expr_equal (a->unary.value, b->unary.value);
Jody Goldberg's avatar
Jody Goldberg committed
534

535 536 537 538 539 540 541 542 543 544 545 546
	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
547

548
	case GNM_EXPR_OP_NAME:
549 550 551
		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
552

553
	case GNM_EXPR_OP_CELLREF:
554
		return gnm_cellref_equal (&a->cellref.ref, &b->cellref.ref);
Jody Goldberg's avatar
Jody Goldberg committed
555

556 557
	case GNM_EXPR_OP_CONSTANT:
		return value_equal (a->constant.value, b->constant.value);
Jody Goldberg's avatar
Jody Goldberg committed
558

559 560 561
	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
562 563 564

		return	aa->cols == ab->cols &&
			aa->rows == ab->rows &&
565 566 567 568 569 570
			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
571 572
	}

573 574 575 576 577 578 579 580 581 582 583
	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
584 585 586 587 588
	}

	return FALSE;
}

589
static GnmCell *
590 591
array_elem_get_corner (GnmExprArrayElem const *elem,
		       Sheet const *sheet, GnmCellPos const *pos)
592
{
593
	GnmCell *corner = sheet_cell_get (sheet,
594
		pos->col - elem->x, pos->row - elem->y);
595 596 597

	/* Sanity check incase the corner gets removed for some reason */
	g_return_val_if_fail (corner != NULL, NULL);
598
	g_return_val_if_fail (gnm_cell_has_expr (corner), NULL);
599 600
	g_return_val_if_fail (corner->base.texpr != (void *)0xdeadbeef, NULL);
	g_return_val_if_fail (IS_GNM_EXPR_TOP (corner->base.texpr), NULL);
601 602 603 604 605

	return corner;
}

static gboolean
Jody Goldberg's avatar
Jody Goldberg committed
606
gnm_expr_extract_ref (GnmRangeRef *res, GnmExpr const *expr,
Morten Welinder's avatar
Morten Welinder committed
607
		      GnmEvalPos const *pos, GnmExprEvalFlags flags)
608
{
609
	switch (GNM_EXPR_GET_OPER (expr)) {
610 611
	case GNM_EXPR_OP_FUNCALL : {
		gboolean failed = TRUE;
Jody Goldberg's avatar
Jody Goldberg committed
612
		GnmValue *v;
613
		GnmFuncEvalInfo ei;
614

615
		ei.pos = pos;
616
		ei.func_call = &expr->func;
617
		v = function_call_with_exprs (&ei, flags);
618 619

		if (v != NULL) {
Jody Goldberg's avatar
Jody Goldberg committed
620 621
			if (v->type == VALUE_CELLRANGE) {
				*res = v->v_range.cell;
622 623 624 625 626 627 628 629
				failed = FALSE;
			}
			value_release (v);
		}
		return failed;
	}

	case GNM_EXPR_OP_CELLREF :
Jody Goldberg's avatar
Jody Goldberg committed
630 631
		res->a = expr->cellref.ref;
		res->b = expr->cellref.ref;
632 633 634
		return FALSE;

	case GNM_EXPR_OP_CONSTANT: {
Jody Goldberg's avatar
Jody Goldberg committed
635
		GnmValue const *v = expr->constant.value;
Jody Goldberg's avatar
Jody Goldberg committed
636 637
		if (v->type == VALUE_CELLRANGE) {
			*res = v->v_range.cell;
638 639 640 641 642 643
			return FALSE;
		}
		return TRUE;
	}

	case GNM_EXPR_OP_NAME:
644
		if (!expr->name.name->active)
645
			return TRUE;
646 647
		return gnm_expr_extract_ref (res, expr->name.name->texpr->expr,
					     pos, flags);
648 649 650 651 652 653
	default :
		break;
	}
	return TRUE;
}

Jody Goldberg's avatar
Jody Goldberg committed
654 655
static inline GnmValue *
handle_empty (GnmValue *res, GnmExprEvalFlags flags)
656 657 658 659 660
{
	if (res == NULL)
		return (flags & GNM_EXPR_EVAL_PERMIT_EMPTY)
		    ? NULL : value_new_int (0);

661
	if (VALUE_IS_EMPTY (res)) {
662 663 664 665 666 667 668
		value_release (res);
		return (flags & GNM_EXPR_EVAL_PERMIT_EMPTY)
		    ? NULL : value_new_int (0);
	}
	return res;
}

Jody Goldberg's avatar
Jody Goldberg committed
669 670
/**
 * value_intersection :
671
 * @v   : a VALUE_CELLRANGE or VALUE_ARRAY
Morten Welinder's avatar
Morten Welinder committed
672
 * @pos :
Jody Goldberg's avatar
Jody Goldberg committed
673 674 675 676 677 678 679 680 681 682 683 684 685 686 687
 *
 * 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
688
static GnmValue *
Morten Welinder's avatar
Morten Welinder committed
689
value_intersection (GnmValue *v, GnmEvalPos const *pos)
Jody Goldberg's avatar
Jody Goldberg committed
690
{
Jody Goldberg's avatar
Jody Goldberg committed
691 692
	GnmValue *res = NULL;
	GnmRange r;
Jody Goldberg's avatar
Jody Goldberg committed
693 694 695 696
	Sheet *start_sheet, *end_sheet;
	gboolean found = FALSE;

	if (v->type == VALUE_ARRAY) {
697 698 699
		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
700 701 702 703 704
		value_release (v);
		return res;
	}

	/* inverted ranges */
705
	gnm_rangeref_normalize (&v->v_range.cell, pos, &start_sheet, &end_sheet, &r);
Jody Goldberg's avatar
Jody Goldberg committed
706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727
	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) {
728
			GnmCell *cell = sheet_cell_get (
Jody Goldberg's avatar
Jody Goldberg committed
729 730 731 732
				eval_sheet (start_sheet, pos->sheet),
				col, row);
			if (cell == NULL)
				return value_new_empty ();
733
			gnm_cell_eval (cell);
734
			return value_dup (cell->value);
Jody Goldberg's avatar
Jody Goldberg committed
735 736 737
		}
	}

738
	return value_new_error_VALUE (pos);
Jody Goldberg's avatar
Jody Goldberg committed
739
}
740

Jody Goldberg's avatar
Jody Goldberg committed
741
static GnmValue *
742 743
bin_arith (GnmExpr const *expr, GnmEvalPos const *ep,
	   GnmValue const *a, GnmValue const *b)
Jody Goldberg's avatar
Jody Goldberg committed
744
{
745 746 747
	gnm_float const va = value_get_as_float (a);
	gnm_float const vb = value_get_as_float (b);
	gnm_float res;
748

749 750 751 752
	switch (GNM_EXPR_GET_OPER (expr)) {
	case GNM_EXPR_OP_ADD:
		res = va + vb;
		break;
753

754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776
	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 ();
777
	}
778

779
	if (gnm_finite (res))
780 781 782
		return value_new_float (res);
	else
		return value_new_error_NUM (ep);
Jody Goldberg's avatar
Jody Goldberg committed
783 784
}

Jody Goldberg's avatar
Jody Goldberg committed
785
static GnmValue *
786
bin_cmp (GnmExprOp op, GnmValDiff comp, GnmEvalPos const *ep)
787 788 789 790 791 792 793 794 795 796 797
{
	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);

798
		return value_new_error_VALUE (ep);
799 800 801 802 803 804 805
	}

	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);
806
	case GNM_EXPR_OP_LTE:	    return value_new_bool (comp != IS_GREATER);
807 808 809 810 811 812 813
	case GNM_EXPR_OP_GTE:	    return value_new_bool (comp != IS_LESS);

#ifndef DEBUG_SWITCH_ENUM
	default:
		g_assert_not_reached ();
#endif
	}
814
	return value_new_error (ep, _("Internal type error"));
815 816
}

Jody Goldberg's avatar
Jody Goldberg committed
817
static GnmValue *
818 819
cb_bin_cmp (GnmEvalPos const *ep, GnmValue const *a, GnmValue const *b,
	    GnmExpr const *expr)
820
{
Morten Welinder's avatar
Try!  
Morten Welinder committed
821
	if (a != NULL && VALUE_IS_ERROR (a))
822
		return value_dup (a);
Morten Welinder's avatar
Try!  
Morten Welinder committed
823
	if (b != NULL && VALUE_IS_ERROR (b))
824
		return value_dup (b);
825
	return bin_cmp (GNM_EXPR_GET_OPER (expr), value_compare (a, b, FALSE), ep);
826 827 828 829 830 831 832 833
}

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
834
	if (a != NULL && VALUE_IS_ERROR (a))
835
		return value_dup (a);
Morten Welinder's avatar
Try!  
Morten Welinder committed
836
	if (b != NULL && VALUE_IS_ERROR (b))
837
		return value_dup (b);
Jody Goldberg's avatar
Jody Goldberg committed
838
	if (VALUE_IS_EMPTY (a))
839
		a = va = (GnmValue *)value_zero;
840
	else if (VALUE_IS_STRING (a)) {
841
		va = format_match_number (value_peek_string (a), NULL,
842 843 844 845 846 847 848
			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
849
	if (VALUE_IS_EMPTY (b))
850
		b = vb = (GnmValue *)value_zero;
851
	else if (VALUE_IS_STRING (b)) {
852
		vb = format_match_number (value_peek_string (b), NULL,
853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877
			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
878
	if (a != NULL && VALUE_IS_ERROR (a))
879
		return value_dup (a);
Morten Welinder's avatar
Try!  
Morten Welinder committed
880
	if (b != NULL && VALUE_IS_ERROR (b))
881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900
		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
901
	GnmEvalPos const *ep;
902 903 904
	GnmValue *res;
	GnmValue const *a, *b;
	BinOpImplicitIteratorFunc	func;
905 906 907

	/* multiply by 0 in unused dimensions.
	 * this is simpler than lots of conditions
908
	 *	state->use_x.a ? x : 0
909 910 911 912
	 **/
	struct {
		int a, b;
	} x, y;
913 914 915 916
	gpointer	user_data;
} BinOpImplicitIteratorState;

static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
917 918
cb_implicit_iter_a_and_b (GnmValueIter const *v_iter,
			  BinOpImplicitIteratorState const *state)
919
{
Jody Goldberg's avatar
Jody Goldberg committed
920 921 922 923 924 925 926 927 928
	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);
929 930 931
	return NULL;
}
static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
932 933
cb_implicit_iter_a_to_scalar_b (GnmValueIter const *v_iter,
				BinOpImplicitIteratorState const *state)
934
{
Jody Goldberg's avatar
Jody Goldberg committed
935 936 937
	state->res->v_array.vals [v_iter->x][v_iter->y] =
		(*state->func) (v_iter->ep,
			v_iter->v, state->b, state->user_data);
938 939
	return NULL;
}
940 941 942 943 944 945 946 947 948 949

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

951
	/* a must be a cellrange or array, it can not be NULL */
Jody Goldberg's avatar
Jody Goldberg committed
952
	iter_info.ep   = ep;
953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984
	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
985
			(GnmValueIterFunc) cb_implicit_iter_a_and_b, &iter_info);
986 987 988 989 990
	} 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
991
			(GnmValueIterFunc) cb_implicit_iter_a_to_scalar_b, &iter_info);
992 993 994 995 996 997 998 999
	}

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

1000
static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
1001 1002
cb_implicit_iter_b_to_scalar_a (GnmValueIter const *v_iter,
				BinOpImplicitIteratorState const *state)
1003
{
Jody Goldberg's avatar
Jody Goldberg committed
1004 1005 1006
	state->res->v_array.vals [v_iter->x][v_iter->y] =
		(*state->func) (v_iter->ep,
			state->a, v_iter->v, state->user_data);
1007 1008 1009
	return NULL;
}
static GnmValue *
1010 1011 1012 1013
bin_array_iter_b (GnmEvalPos const *ep,
		  GnmValue *a, GnmValue *b,
		  BinOpImplicitIteratorFunc func,
		  GnmExpr const *expr)
1014 1015
{
	BinOpImplicitIteratorState iter_info;
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026

	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
1027
		(GnmValueIterFunc) cb_implicit_iter_b_to_scalar_a, &iter_info);
1028 1029
	if (a != NULL)
		value_release (a);
1030 1031
	value_release (b);

1032 1033 1034
	return iter_info.res;
}

1035
static GnmValue *
1036
negate_value (GnmValue const *v)
1037
{
1038 1039 1040 1041
	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;
1042
	} else
1043 1044 1045 1046
		return NULL;
}

static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
1047
cb_iter_unary_neg (GnmValueIter const *v_iter, GnmValue *res)
1048
{
Jody Goldberg's avatar
Jody Goldberg committed
1049
	GnmValue const *v = v_iter->v;
1050 1051 1052 1053
	GnmValue *tmp = NULL;

	if (VALUE_IS_EMPTY (v))
		tmp = value_new_int (0);
Morten Welinder's avatar
Try!  
Morten Welinder committed
1054
	else if (VALUE_IS_ERROR (v))
1055
		tmp = value_dup (v);
1056
	else if (VALUE_IS_STRING (v)) {
Jody Goldberg's avatar
Jody Goldberg committed
1057 1058 1059
		GnmValue *conv = format_match_number (
			value_peek_string (v), NULL,
			workbook_date_conv (v_iter->ep->sheet->workbook));
1060 1061 1062 1063
		if (conv != NULL) {
			tmp = negate_value (conv);
			value_release (conv);
		}
1064 1065
	} else {
		/* BOOL goes here.  */
1066
		tmp = negate_value (v);
1067
	}
1068

Jody Goldberg's avatar
Jody Goldberg committed
1069 1070 1071
	if (NULL == tmp)
		tmp = value_new_error_VALUE (v_iter->ep);
	res->v_array.vals[v_iter->x][v_iter->y] = tmp;
1072 1073 1074 1075
	return NULL;
}

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

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

		if (VALUE_IS_NUMBER (v)){
			tmp = value_new_float (value_get_as_float (v) / 100);
1097
			value_set_fmt (tmp, go_format_default_percentage ());
1098
		} else
Jody Goldberg's avatar
Jody Goldberg committed
1099
			tmp = value_new_error_VALUE (v_iter->ep);
1100

1101
		if (conv != NULL)
1102
			value_release (conv);
1103 1104
	}

Jody Goldberg's avatar
Jody Goldberg committed
1105
	res->v_array.vals[v_iter->x][v_iter->y] = tmp;
1106
	return NULL;
1107 1108
}