GitLab repository storage has been migrated to hashed layout. Please contact Infrastructure team if you notice any issues with repositories or hooks.

expr.c 78.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 "func.h"
Jody Goldberg's avatar
Jody Goldberg committed
31
#include "cell.h"
Jody Goldberg's avatar
Jody Goldberg committed
32
#include "sheet.h"
33
#include "value.h"
34
#include "parse-util.h"
35
#include "ranges.h"
36
#include "number-match.h"
Jody Goldberg's avatar
Jody Goldberg committed
37
#include "workbook-priv.h"
Jeffrey Stedfast's avatar
Jeffrey Stedfast committed
38
#include "gutils.h"
39
#include "parse-util.h"
40
#include "mathfunc.h"
41

42 43
#include <math.h>
#include <string.h>
Jody Goldberg's avatar
Jody Goldberg committed
44
#include <stdlib.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>
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
	ans = CHUNK_ALLOC (GnmExprConstant, expression_pool_small);
81 82
	if (!ans)
		return NULL;
83
	gnm_expr_constant_init (ans, v);
84

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

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

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

96
	ans = CHUNK_ALLOC (GnmExprFunction, expression_pool_small);
97

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

104
	return (GnmExpr *)ans;
105
}
106

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

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

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

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

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

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

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

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

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

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

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

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

199
	ans->oper = op;
200 201
	ans->value_a = l;
	ans->value_b = r;
202

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

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

208 209
GnmExpr const *
gnm_expr_new_name (GnmNamedExpr *name,
210
		   Sheet *optional_scope, Workbook *optional_wb_scope)
Morten Welinder's avatar
Morten Welinder committed
211
{
212
	GnmExprName *ans;
Morten Welinder's avatar
Morten Welinder committed
213

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

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

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

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

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

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

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

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

242
	return (GnmExpr *)ans;
243 244
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Jody Goldberg's avatar
Jody Goldberg committed
317
/***************************************************************************/
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

/**
 * 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
352

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

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

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

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

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

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

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
	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
437

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

447 448 449 450
	case GNM_EXPR_OP_FUNCALL: {
		int i;

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

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

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

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

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

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

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

488 489 490 491
	case GNM_EXPR_OP_SET: {
		int i;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	return FALSE;
}

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

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

	return corner;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

950
	/* a must be a cellrange or array, it can not be NULL */
Jody Goldberg's avatar
Jody Goldberg committed
951
	iter_info.ep   = ep;
952 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
	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
984
			(GnmValueIterFunc) cb_implicit_iter_a_and_b, &iter_info);
985 986 987 988 989
	} 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
990
			(GnmValueIterFunc) cb_implicit_iter_a_to_scalar_b, &iter_info);
991 992 993 994 995 996 997 998
	}

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

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

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

1031 1032 1033
	return iter_info.res;
}

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

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

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

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

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

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

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

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

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

Jody Goldberg's avatar
Jody Goldberg committed
1108