expr.c 72.3 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-2002 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 33
#include "sheet.h"
#include "str.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-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
}


Jody Goldberg's avatar
Jody Goldberg committed
156 157
/***************************************************************************/

158 159
GnmExpr const *
gnm_expr_new_unary  (GnmExprOp op, GnmExpr const *e)
Morten Welinder's avatar
Morten Welinder committed
160
{
161
	GnmExprUnary *ans;
Morten Welinder's avatar
Morten Welinder committed
162

163
	ans = CHUNK_ALLOC (GnmExprUnary, expression_pool_small);
164 165 166
	if (!ans)
		return NULL;

167
	ans->oper = op;
168
	ans->value = e;
169

170
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
171 172
}

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

175 176
GnmExpr const *
gnm_expr_new_binary (GnmExpr const *l, GnmExprOp op, GnmExpr const *r)
Morten Welinder's avatar
Morten Welinder committed
177
{
178
	GnmExprBinary *ans;
Morten Welinder's avatar
Morten Welinder committed
179

180
	ans = CHUNK_ALLOC (GnmExprBinary, expression_pool_small);
181 182
	if (!ans)
		return NULL;
183

184
	ans->oper = op;
185 186
	ans->value_a = l;
	ans->value_b = r;
187

188
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
189 190
}

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

193 194
GnmExpr const *
gnm_expr_new_name (GnmNamedExpr *name,
195
		   Sheet *optional_scope, Workbook *optional_wb_scope)
Morten Welinder's avatar
Morten Welinder committed
196
{
197
	GnmExprName *ans;
Morten Welinder's avatar
Morten Welinder committed
198

199
	ans = CHUNK_ALLOC (GnmExprName, expression_pool_big);
200 201
	if (!ans)
		return NULL;
202

203
	ans->oper = GNM_EXPR_OP_NAME;
204
	ans->name = name;
205
	expr_name_ref (name);
206

207 208 209
	ans->optional_scope = optional_scope;
	ans->optional_wb_scope = optional_wb_scope;

210
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
211
}
212

Jody Goldberg's avatar
Jody Goldberg committed
213 214
/***************************************************************************/

215
GnmExpr const *
Jody Goldberg's avatar
Jody Goldberg committed
216
gnm_expr_new_cellref (GnmCellRef const *cr)
217
{
218
	GnmExprCellRef *ans;
219

220
	ans = CHUNK_ALLOC (GnmExprCellRef, expression_pool_big);
221 222
	if (!ans)
		return NULL;
223

224
	ans->oper = GNM_EXPR_OP_CELLREF;
225 226
	ans->ref = *cr;

227
	return (GnmExpr *)ans;
228 229
}

Jody Goldberg's avatar
Jody Goldberg committed
230 231 232
/***************************************************************************/

/**
233
 * gnm_expr_new_array_corner :
Jody Goldberg's avatar
Jody Goldberg committed
234 235 236 237 238 239
 * @cols :
 * @rows :
 * @expr : optionally NULL.
 *
 * Absorb a referernce to @expr if it is non NULL.
 **/
240
static GnmExpr const *
241
gnm_expr_new_array_corner(int cols, int rows, GnmExpr const *expr)
242
{
243
	GnmExprArrayCorner *ans;
244

245
	ans = CHUNK_ALLOC (GnmExprArrayCorner, expression_pool_big);
246 247
	if (ans == NULL)
		return NULL;
248

249
	ans->oper = GNM_EXPR_OP_ARRAY_CORNER;
250 251
	ans->rows = rows;
	ans->cols = cols;
252 253 254 255 256
	ans->value = NULL;
	ans->expr = expr;
	return (GnmExpr *)ans;
}

257
static GnmExpr const *
258 259 260 261
gnm_expr_new_array_elem  (int x, int y)
{
	GnmExprArrayElem *ans;

262
	ans = CHUNK_ALLOC (GnmExprArrayElem, expression_pool_small);
263 264 265
	if (ans == NULL)
		return NULL;

266
	ans->oper = GNM_EXPR_OP_ARRAY_ELEM;
267 268
	ans->x = x;
	ans->y = y;
269
	return (GnmExpr *)ans;
270 271
}

Jody Goldberg's avatar
Jody Goldberg committed
272 273
/***************************************************************************/

274 275
static GnmExpr const *
gnm_expr_new_setv (int argc, GnmExprConstPtr *argv)
Jody Goldberg's avatar
Jody Goldberg committed
276
{
277 278
	GnmExprSet *ans = CHUNK_ALLOC (GnmExprSet, expression_pool_small);

279
	ans->oper = GNM_EXPR_OP_SET;
280 281 282 283
	ans->argc = argc;
	ans->argv = argv;

	return (GnmExpr *)ans;
Jody Goldberg's avatar
Jody Goldberg committed
284 285
}

286 287
GnmExpr const *
gnm_expr_new_set (GnmExprList *set)
288
{
289 290 291
	int i, argc;
	GnmExprConstPtr *argv;
	GnmExprList *set0 = set;
292

293 294 295 296 297
	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);
298

299
	return gnm_expr_new_setv (argc, argv);
300 301
}

Jody Goldberg's avatar
Jody Goldberg committed
302 303
/***************************************************************************/

304 305
GnmExpr const *
gnm_expr_copy (GnmExpr const *expr)
306
{
307 308
	g_return_val_if_fail (expr != NULL, NULL);

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

318 319 320 321
	case GNM_EXPR_OP_ANY_UNARY:
		return gnm_expr_new_unary
			(GNM_EXPR_GET_OPER (expr),
			 gnm_expr_copy (expr->unary.value));
322

323 324 325 326
	case GNM_EXPR_OP_FUNCALL: {
		GnmExprConstPtr *argv =
			g_new (GnmExprConstPtr, expr->func.argc);
		int i;
Arturo Espinosa's avatar
Arturo Espinosa committed
327

328 329
		for (i = 0; i < expr->func.argc; i++)
			argv[i] = gnm_expr_copy (expr->func.argv[i]);
330

331 332 333 334 335
		return gnm_expr_new_funcallv
			(expr->func.func,
			 expr->func.argc,
			 argv);
	}
336

337 338 339 340 341 342 343 344 345 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 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387
	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
388

389
	switch (GNM_EXPR_GET_OPER (expr)) {
390
	case GNM_EXPR_OP_RANGE_CTOR:
391
	case GNM_EXPR_OP_INTERSECT:
392
	case GNM_EXPR_OP_ANY_BINARY:
393 394
		gnm_expr_free (expr->binary.value_a);
		gnm_expr_free (expr->binary.value_b);
395
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
Arturo Espinosa's avatar
Arturo Espinosa committed
396
		break;
397

398 399 400 401
	case GNM_EXPR_OP_FUNCALL: {
		int i;

		for (i = 0; i < expr->func.argc; i++)
402
			gnm_expr_free (expr->func.argv[i]);
Morten Welinder's avatar
Morten Welinder committed
403
		g_free (expr->func.argv);
Jody Goldberg's avatar
Jody Goldberg committed
404
		gnm_func_unref (expr->func.func);
405
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
Arturo Espinosa's avatar
Arturo Espinosa committed
406
		break;
407
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
408

409
	case GNM_EXPR_OP_NAME:
410
		expr_name_unref (expr->name.name);
411
		CHUNK_FREE (expression_pool_big, (gpointer)expr);
Michael Meeks's avatar
Michael Meeks committed
412 413
		break;

414
	case GNM_EXPR_OP_CONSTANT:
Jody Goldberg's avatar
Jody Goldberg committed
415
		value_release ((GnmValue *)expr->constant.value);
416
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
417 418 419
		break;

	case GNM_EXPR_OP_CELLREF:
420
		CHUNK_FREE (expression_pool_big, (gpointer)expr);
Arturo Espinosa's avatar
Arturo Espinosa committed
421 422
		break;

423
	case GNM_EXPR_OP_ANY_UNARY:
424
		gnm_expr_free (expr->unary.value);
425
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
Arturo Espinosa's avatar
Arturo Espinosa committed
426
		break;
427

428 429 430
	case GNM_EXPR_OP_ARRAY_CORNER:
		if (expr->array_corner.value)
			value_release (expr->array_corner.value);
431
		gnm_expr_free (expr->array_corner.expr);
432
		CHUNK_FREE (expression_pool_big, (gpointer)expr);
433 434 435
		break;

	case GNM_EXPR_OP_ARRAY_ELEM:
436
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
Jody Goldberg's avatar
Jody Goldberg committed
437
		break;
438

439 440 441 442
	case GNM_EXPR_OP_SET: {
		int i;

		for (i = 0; i < expr->set.argc; i++)
443
			gnm_expr_free (expr->set.argv[i]);
Morten Welinder's avatar
Morten Welinder committed
444
		g_free (expr->set.argv);
445
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
446
		break;
447
	}
448 449

#ifndef DEBUG_SWITCH_ENUM
450
	default:
451
		g_assert_not_reached ();
452
		break;
453
#endif
Arturo Espinosa's avatar
Arturo Espinosa committed
454
	}
455 456
}

Jody Goldberg's avatar
Jody Goldberg committed
457
/**
458
 * gnm_expr_equal : Returns TRUE if the supplied expressions are exactly the
Jody Goldberg's avatar
Jody Goldberg committed
459 460 461 462
 *   same.  No eval position is used to see if they are effectively the same.
 *   Named expressions must refer the the same name, having equivalent names is
 *   insufficeient.
 */
463
static gboolean
464
gnm_expr_equal (GnmExpr const *a, GnmExpr const *b)
Jody Goldberg's avatar
Jody Goldberg committed
465 466 467 468 469 470 471
{
	if (a == b)
		return TRUE;

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

472
	if (GNM_EXPR_GET_OPER (a) != GNM_EXPR_GET_OPER (b))
Jody Goldberg's avatar
Jody Goldberg committed
473 474
		return FALSE;

475
	switch (GNM_EXPR_GET_OPER (a)) {
476
	case GNM_EXPR_OP_RANGE_CTOR:
477
	case GNM_EXPR_OP_INTERSECT:
478 479 480
	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
481

482 483
	case GNM_EXPR_OP_ANY_UNARY:
		return gnm_expr_equal (a->unary.value, b->unary.value);
Jody Goldberg's avatar
Jody Goldberg committed
484

485 486 487 488 489 490 491 492 493 494 495 496
	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
497

498
	case GNM_EXPR_OP_NAME:
499 500 501
		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
502

503
	case GNM_EXPR_OP_CELLREF:
504
		return gnm_cellref_equal (&a->cellref.ref, &b->cellref.ref);
Jody Goldberg's avatar
Jody Goldberg committed
505

506 507
	case GNM_EXPR_OP_CONSTANT:
		return value_equal (a->constant.value, b->constant.value);
Jody Goldberg's avatar
Jody Goldberg committed
508

509 510 511
	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
512 513 514

		return	aa->cols == ab->cols &&
			aa->rows == ab->rows &&
515 516 517 518 519 520
			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
521 522
	}

523 524 525 526 527 528 529 530 531 532 533
	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
534 535 536 537 538
	}

	return FALSE;
}

539
static GnmCell *
540 541
array_elem_get_corner (GnmExprArrayElem const *elem,
		       Sheet const *sheet, GnmCellPos const *pos)
542
{
543
	GnmCell *corner = sheet_cell_get (sheet,
544
		pos->col - elem->x, pos->row - elem->y);
545 546 547 548

	/* Sanity check incase the corner gets removed for some reason */
	g_return_val_if_fail (corner != NULL, NULL);
	g_return_val_if_fail (cell_has_expr (corner), NULL);
549 550
	g_return_val_if_fail (corner->base.texpr != (void *)0xdeadbeef, NULL);
	g_return_val_if_fail (IS_GNM_EXPR_TOP (corner->base.texpr), NULL);
551 552 553 554 555

	return corner;
}

static gboolean
Jody Goldberg's avatar
Jody Goldberg committed
556
gnm_expr_extract_ref (GnmRangeRef *res, GnmExpr const *expr,
Morten Welinder's avatar
Morten Welinder committed
557
		      GnmEvalPos const *pos, GnmExprEvalFlags flags)
558
{
559
	switch (GNM_EXPR_GET_OPER (expr)) {
560 561
	case GNM_EXPR_OP_FUNCALL : {
		gboolean failed = TRUE;
Jody Goldberg's avatar
Jody Goldberg committed
562
		GnmValue *v;
563 564
		FunctionEvalInfo ei;
		ei.pos = pos;
565
		ei.func_call = &expr->func;
566

567 568 569 570
		v = function_call_with_exprs (&ei,
					      expr->func.argc,
					      expr->func.argv,
					      flags);
571
		if (v != NULL) {
Jody Goldberg's avatar
Jody Goldberg committed
572 573
			if (v->type == VALUE_CELLRANGE) {
				*res = v->v_range.cell;
574 575 576 577 578 579 580 581
				failed = FALSE;
			}
			value_release (v);
		}
		return failed;
	}

	case GNM_EXPR_OP_CELLREF :
Jody Goldberg's avatar
Jody Goldberg committed
582 583
		res->a = expr->cellref.ref;
		res->b = expr->cellref.ref;
584 585 586
		return FALSE;

	case GNM_EXPR_OP_CONSTANT: {
Jody Goldberg's avatar
Jody Goldberg committed
587
		GnmValue const *v = expr->constant.value;
Jody Goldberg's avatar
Jody Goldberg committed
588 589
		if (v->type == VALUE_CELLRANGE) {
			*res = v->v_range.cell;
590 591 592 593 594 595
			return FALSE;
		}
		return TRUE;
	}

	case GNM_EXPR_OP_NAME:
596
		if (!expr->name.name->active)
597
			return TRUE;
598 599
		return gnm_expr_extract_ref (res, expr->name.name->texpr->expr,
					     pos, flags);
600 601 602 603 604 605
	default :
		break;
	}
	return TRUE;
}

Jody Goldberg's avatar
Jody Goldberg committed
606 607
static inline GnmValue *
handle_empty (GnmValue *res, GnmExprEvalFlags flags)
608 609 610 611 612
{
	if (res == NULL)
		return (flags & GNM_EXPR_EVAL_PERMIT_EMPTY)
		    ? NULL : value_new_int (0);

613
	if (VALUE_IS_EMPTY (res)) {
614 615 616 617 618 619 620
		value_release (res);
		return (flags & GNM_EXPR_EVAL_PERMIT_EMPTY)
		    ? NULL : value_new_int (0);
	}
	return res;
}

Jody Goldberg's avatar
Jody Goldberg committed
621 622
/**
 * value_intersection :
623
 * @v   : a VALUE_CELLRANGE or VALUE_ARRAY
Morten Welinder's avatar
Morten Welinder committed
624
 * @pos :
Jody Goldberg's avatar
Jody Goldberg committed
625 626 627 628 629 630 631 632 633 634 635 636 637 638 639
 *
 * 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
640
static GnmValue *
Morten Welinder's avatar
Morten Welinder committed
641
value_intersection (GnmValue *v, GnmEvalPos const *pos)
Jody Goldberg's avatar
Jody Goldberg committed
642
{
Jody Goldberg's avatar
Jody Goldberg committed
643 644
	GnmValue *res = NULL;
	GnmRange r;
Jody Goldberg's avatar
Jody Goldberg committed
645 646 647 648
	Sheet *start_sheet, *end_sheet;
	gboolean found = FALSE;

	if (v->type == VALUE_ARRAY) {
649
		res = value_dup (v->v_array.vals[0][0]);
Jody Goldberg's avatar
Jody Goldberg committed
650 651 652 653 654
		value_release (v);
		return res;
	}

	/* inverted ranges */
655
	gnm_rangeref_normalize (&v->v_range.cell, pos, &start_sheet, &end_sheet, &r);
Jody Goldberg's avatar
Jody Goldberg committed
656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677
	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) {
678
			GnmCell *cell = sheet_cell_get (
Jody Goldberg's avatar
Jody Goldberg committed
679 680 681 682 683
				eval_sheet (start_sheet, pos->sheet),
				col, row);
			if (cell == NULL)
				return value_new_empty ();
			cell_eval (cell);
684
			return value_dup (cell->value);
Jody Goldberg's avatar
Jody Goldberg committed
685 686 687
		}
	}

688
	return value_new_error_VALUE (pos);
Jody Goldberg's avatar
Jody Goldberg committed
689
}
690

Jody Goldberg's avatar
Jody Goldberg committed
691
static GnmValue *
692 693
bin_arith (GnmExpr const *expr, GnmEvalPos const *ep,
	   GnmValue const *a, GnmValue const *b)
Jody Goldberg's avatar
Jody Goldberg committed
694
{
695 696 697
	gnm_float const va = value_get_as_float (a);
	gnm_float const vb = value_get_as_float (b);
	gnm_float res;
698

699 700 701 702
	switch (GNM_EXPR_GET_OPER (expr)) {
	case GNM_EXPR_OP_ADD:
		res = va + vb;
		break;
703

704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726
	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 ();
727
	}
728

729
	if (gnm_finite (res))
730 731 732
		return value_new_float (res);
	else
		return value_new_error_NUM (ep);
Jody Goldberg's avatar
Jody Goldberg committed
733 734
}

Jody Goldberg's avatar
Jody Goldberg committed
735
static GnmValue *
736
bin_cmp (GnmExprOp op, GnmValDiff comp, GnmEvalPos const *ep)
737 738 739 740 741 742 743 744 745 746 747
{
	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);

748
		return value_new_error_VALUE (ep);
749 750 751 752 753 754 755 756 757 758 759 760 761 762 763
	}

	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);
	case GNM_EXPR_OP_LTE: 	    return value_new_bool (comp != IS_GREATER);
	case GNM_EXPR_OP_GTE:	    return value_new_bool (comp != IS_LESS);

#ifndef DEBUG_SWITCH_ENUM
	default:
		g_assert_not_reached ();
#endif
	}
764
	return value_new_error (ep, _("Internal type error"));
765 766
}

Jody Goldberg's avatar
Jody Goldberg committed
767
static GnmValue *
768 769
cb_bin_cmp (GnmEvalPos const *ep, GnmValue const *a, GnmValue const *b,
	    GnmExpr const *expr)
770
{
Morten Welinder's avatar
Try!  
Morten Welinder committed
771
	if (a != NULL && VALUE_IS_ERROR (a))
772
		return value_dup (a);
Morten Welinder's avatar
Try!  
Morten Welinder committed
773
	if (b != NULL && VALUE_IS_ERROR (b))
774
		return value_dup (b);
775
	return bin_cmp (GNM_EXPR_GET_OPER (expr), value_compare (a, b, FALSE), ep);
776 777 778 779 780 781 782 783
}

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
784
	if (a != NULL && VALUE_IS_ERROR (a))
785
		return value_dup (a);
Morten Welinder's avatar
Try!  
Morten Welinder committed
786
	if (b != NULL && VALUE_IS_ERROR (b))
787
		return value_dup (b);
Jody Goldberg's avatar
Jody Goldberg committed
788
	if (VALUE_IS_EMPTY (a))
789
		a = va = (GnmValue *)value_zero;
790
	else if (VALUE_IS_STRING (a)) {
791 792 793 794 795 796 797 798
		va = format_match_number (a->v_str.val->str, NULL,
			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
799
	if (VALUE_IS_EMPTY (b))
800
		b = vb = (GnmValue *)value_zero;
801
	else if (VALUE_IS_STRING (b)) {
802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827
		vb = format_match_number (b->v_str.val->str, NULL,
			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
828
	if (a != NULL && VALUE_IS_ERROR (a))
829
		return value_dup (a);
Morten Welinder's avatar
Try!  
Morten Welinder committed
830
	if (b != NULL && VALUE_IS_ERROR (b))
831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 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 877 878 879 880 881 882
		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 {
	GnmValue *res;
	GnmValue const *a, *b;
	BinOpImplicitIteratorFunc	func;
	gpointer	user_data;
} BinOpImplicitIteratorState;

static GnmValue *
cb_implicit_iter_a_to_b (GnmValue const *v, GnmEvalPos const *ep,
			 int x, int y, BinOpImplicitIteratorState const *state)
{
	state->res->v_array.vals [x][y] = (*state->func) (ep,
		v, value_area_get_x_y (state->b, x, y, ep), state->user_data);
	return NULL;
}
static GnmValue *
cb_implicit_iter_a_to_scalar_b (GnmValue const *v, GnmEvalPos const *ep,
				int x, int y, BinOpImplicitIteratorState const *state)
{
	state->res->v_array.vals [x][y] = (*state->func) (ep,
		v, state->b, state->user_data);
	return NULL;
}
static GnmValue *
cb_implicit_iter_b_to_scalar_a (GnmValue const *v, GnmEvalPos const *ep,
				int x, int y, BinOpImplicitIteratorState const *state)
{
	state->res->v_array.vals [x][y] = (*state->func) (ep,
		state->a, v, state->user_data);
	return NULL;
}

static GnmValue *
Morten Welinder's avatar
Typo.  
Morten Welinder committed
883 884
bin_array_op (GnmEvalPos const *ep, const GnmValue *sizer,
	      GnmValue *a, GnmValue *b,
885 886 887 888
	      BinOpImplicitIteratorFunc func, gpointer user_data)
{
	BinOpImplicitIteratorState iter_info;
	
Morten Welinder's avatar
Try!  
Morten Welinder committed
889
	if (sizer != a || b == NULL || !VALUE_IS_ERROR (b)) {
890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907
		iter_info.func = func;
		iter_info.user_data = user_data;
		iter_info.a = a;
		iter_info.b = b;
		iter_info.res = value_new_array_empty (
			value_area_get_width  (sizer, ep),
			value_area_get_height (sizer, ep));
		if (sizer == b)
			value_area_foreach (b, ep, CELL_ITER_ALL,
				(ValueAreaFunc) cb_implicit_iter_b_to_scalar_a, &iter_info);
		else if (b != NULL &&
			   (b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY))
			value_area_foreach (a, ep, CELL_ITER_ALL,
				(ValueAreaFunc) cb_implicit_iter_a_to_b, &iter_info);
		else
			value_area_foreach (a, ep, CELL_ITER_ALL,
				(ValueAreaFunc) cb_implicit_iter_a_to_scalar_b, &iter_info);
	} else
Morten Welinder's avatar
Typo.  
Morten Welinder committed
908
		/* you have to love the asymmetry of MS XL */
909 910 911 912 913 914 915 916
		iter_info.res = value_new_error_VALUE (ep);
	if (a != NULL)
		value_release (a);
	if (b != NULL)
		value_release (b);
	return iter_info.res;
}

917
static GnmValue *
918
negate_value (GnmValue const *v)
919
{
920 921 922 923
	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;
924
	} else
925 926 927 928 929 930 931 932 933 934 935
		return NULL;
}

static GnmValue *
cb_iter_unary_neg (GnmValue const *v, GnmEvalPos const *ep,
		   int x, int y, GnmValue *res)
{
	GnmValue *tmp = NULL;

	if (VALUE_IS_EMPTY (v))
		tmp = value_new_int (0);
Morten Welinder's avatar
Try!  
Morten Welinder committed
936
	else if (VALUE_IS_ERROR (v))
937
		tmp = value_dup (v);
938
	else if (VALUE_IS_STRING (v)) {
939
		GnmValue *conv = format_match_number
940
			(value_peek_string (v), NULL,
941 942 943 944 945
			 workbook_date_conv (ep->sheet->workbook));
		if (conv != NULL) {
			tmp = negate_value (conv);
			value_release (conv);
		}
946 947
	} else {
		/* BOOL goes here.  */
948
		tmp = negate_value (v);
949
	}
950 951 952 953

	if (!tmp)
		tmp = value_new_error_VALUE (ep);

954
	res->v_array.vals[x][y] = tmp;
955 956 957 958 959 960 961
	return NULL;
}

static GnmValue *
cb_iter_percentage (GnmValue const *v, GnmEvalPos const *ep,
		    int x, int y, GnmValue *res)
{
962
	GnmValue *tmp;
963 964 965

	if (VALUE_IS_EMPTY (v))
		tmp = value_new_int (0);
Morten Welinder's avatar
Try!  
Morten Welinder committed
966
	else if (VALUE_IS_ERROR (v))
967
		tmp = value_dup (v);
968 969
	else {
		GnmValue *conv = NULL;
970
		if (VALUE_IS_STRING (v)) {
971
			conv = format_match_number (value_peek_string (v), NULL,
972 973 974 975 976 977 978
						    workbook_date_conv (ep->sheet->workbook));
			if (conv != NULL)
				v = conv;
		}

		if (VALUE_IS_NUMBER (v)){
			tmp = value_new_float (value_get_as_float (v) / 100);
979
			value_set_fmt (tmp, go_format_default_percentage ());
980 981 982
		} else
			tmp = value_new_error_VALUE (ep);

983
		if (conv != NULL)
984
			value_release (conv);
985 986
	}

987
	res->v_array.vals[x][y] = tmp;
988
	return NULL;
989 990
}

Jody Goldberg's avatar
Jody Goldberg committed
991 992 993 994 995 996 997 998 999 1000 1001 1002 1003
static GnmValue *
gnm_expr_range_op (GnmExpr const *expr, GnmEvalPos const *ep,
		   GnmExprEvalFlags flags)
{
	GnmRangeRef a_ref, b_ref;
	GnmRange a_range, b_range, res_range;
	Sheet *a_start, *a_end, *b_start, *b_end;
	GnmValue *res = NULL;

	if (gnm_expr_extract_ref (&a_ref, expr->binary.value_a, ep, flags) ||
	    gnm_expr_extract_ref (&b_ref, expr->binary.value_b, ep, flags))
		return value_new_error_REF (ep);

1004 1005
	gnm_rangeref_normalize (&a_ref, ep, &a_start, &a_end, &a_range);
	gnm_rangeref_normalize (&b_ref, ep, &b_start, &b_end, &b_range);
Jody Goldberg's avatar
Jody Goldberg committed
1006

1007
	if (GNM_EXPR_GET_OPER (expr) != GNM_EXPR_OP_INTERSECT)
Jody Goldberg's avatar
Jody Goldberg committed
1008 1009 1010 1011 1012
		res_range = range_union (&a_range, &b_range);
	else if (!range_intersection  (&res_range, &a_range, &b_range))
		return value_new_error_NULL (ep);

	res = value_new_cellrange_r (a_start, &res_range);
1013
	dependent_add_dynamic_dep (ep->dep, &res->v_range.cell);
Jody Goldberg's avatar
Jody Goldberg committed
1014 1015 1016 1017 1018 1019 1020 1021 1022
	if (!(flags & GNM_EXPR_EVAL_PERMIT_NON_SCALAR)) {
		res = value_intersection (res, ep);
		return (res != NULL)
			? handle_empty (res, flags)
			: value_new_error_VALUE (ep);
	}
	return res;
}

1023 1024 1025 1026 1027 1028 1029 1030
/**
 * gnm_expr_eval :
 * @expr :
 * @ep   :
 * @flags:
 *
 * if GNM_EXPR_EVAL_PERMIT_EMPTY is not set then return int(0) if the
 * expression returns empty, or the  value of an unused cell.
1031
 **/
Jody Goldberg's avatar
Jody Goldberg committed
1032
GnmValue *
Morten Welinder's avatar
Morten Welinder committed
1033
gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos,
1034
	       GnmExprEvalFlags flags)
Arturo Espinosa's avatar
Arturo Espinosa committed
1035
{
Jody Goldberg's avatar
Jody Goldberg committed
1036
	GnmValue *res = NULL, *a = NULL, *b = NULL;
1037

1038 1039
	g_return_val_if_fail (expr != NULL, handle_empty (NULL, flags));
	g_return_val_if_fail (pos != NULL, handle_empty (NULL, flags));
1040

1041
	switch (GNM_EXPR_GET_OPER (expr)){
1042 1043 1044 1045 1046
	case GNM_EXPR_OP_EQUAL:
	case GNM_EXPR_OP_NOT_EQUAL:
	case GNM_EXPR_OP_GT:
	case GNM_EXPR_OP_GTE:
	case GNM_EXPR_OP_LT:
1047
	case GNM_EXPR_OP_LTE:
Jody Goldberg's avatar
Jody Goldberg committed
1048
		flags |= GNM_EXPR_EVAL_PERMIT_EMPTY;
Morten Welinder's avatar
Morten Welinder committed
1049

Jody Goldberg's avatar
Jody Goldberg committed
1050
		a = gnm_expr_eval (expr->binary.value_a, pos, flags);
1051
		if (a != NULL) {
Morten Welinder's avatar
Try!  
Morten Welinder committed
1052
			if (VALUE_IS_ERROR (a))
1053 1054 1055 1056 1057 1058 1059
				return a;
			if (a->type == VALUE_CELLRANGE || a->type == VALUE_ARRAY)
				return bin_array_op (pos, a, a,
					gnm_expr_eval (expr->binary.value_b, pos, flags),
					(BinOpImplicitIteratorFunc) cb_bin_cmp,
					(gpointer) expr);
		}
Jody Goldberg's avatar
Jody Goldberg committed
1060 1061

		b = gnm_expr_eval (expr->binary.value_b, pos, flags);
1062
		if (b != NULL) {
Morten Welinder's avatar
Try!  
Morten Welinder committed
1063
			if (VALUE_IS_ERROR (b)) {
1064 1065 1066 1067 1068 1069 1070 1071
				if (a != NULL)
					value_release (a);
				return b;
			}
			if (b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY)
				return bin_array_op (pos, b, a, b,
					(BinOpImplicitIteratorFunc) cb_bin_cmp,
					(gpointer) expr);
Morten Welinder's avatar
Morten Welinder committed
1072
		}
1073

1074
		res = bin_cmp (GNM_EXPR_GET_OPER (expr), value_compare (a, b, FALSE), pos);
1075 1076 1077 1078
		if (a != NULL)
			value_release (a);
		if (b != NULL)
			value_release (b);
1079
		return res;
1080

1081 1082 1083 1084 1085
	case GNM_EXPR_OP_ADD:
	case GNM_EXPR_OP_SUB:
	case GNM_EXPR_OP_MULT:
	case GNM_EXPR_OP_DIV:
	case GNM_EXPR_OP_EXP:
1086 1087 1088 1089 1090 1091 1092 1093 1094
		/*
		 * Priority
		 * 1) Error from A
		 * 2) #!VALUE error if A is not a number
		 * 3) Error from B
		 * 4) #!VALUE error if B is not a number
		 * 5) result of operation, or error specific to the operation
		 */

Jody Goldberg's avatar
Jody Goldberg committed
1095
	        /* Guarantees value != NULL */
1096
		flags &= ~GNM_EXPR_EVAL_PERMIT_EMPTY;
Jody Goldberg's avatar
Jody Goldberg committed
1097

1098
		/* 1) Error from A */
Jody Goldberg's avatar
Jody Goldberg committed
1099
		a = gnm_expr_eval (expr->binary.value_a, pos, flags);
Morten Welinder's avatar
Try!  
Morten Welinder committed
1100
		if (VALUE_IS_ERROR (a))
1101
			return value_error_set_pos (&a->v_err, pos);
1102

1103
		/* 2) #!VALUE error if A is not a number */
1104
		if (VALUE_IS_STRING (a)) {
Jody Goldberg's avatar
Jody Goldberg committed
1105
			GnmValue *tmp = format_match_number (a->v_str.val->str, NULL,
1106
				workbook_date_conv (pos->sheet->workbook));
1107 1108