expr.c 75.8 KB
Newer Older
1
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
Miguel de Icaza's avatar
Miguel de Icaza committed
2
/*
3
 * expr.c : Expression evaluation in Gnumeric
Miguel de Icaza's avatar
Miguel de Icaza committed
4
 *
5
 * Copyright (C) 2001-2006 Jody Goldberg (jody@gnome.org)
6
 * Copyright (C) 1998-2000 Miguel de Icaza (miguel@gnu.org)
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-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
}


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

228
	return (GnmExpr *)ans;
229 230
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

332 333 334 335 336
		return gnm_expr_new_funcallv
			(expr->func.func,
			 expr->func.argc,
			 argv);
	}
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 388
	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
389

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

399 400 401 402
	case GNM_EXPR_OP_FUNCALL: {
		int i;

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

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

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

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

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

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

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

440 441 442 443
	case GNM_EXPR_OP_SET: {
		int i;

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

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

Jody Goldberg's avatar
Jody Goldberg committed
458
/**
459
 * gnm_expr_equal : Returns TRUE if the supplied expressions are exactly the
Jody Goldberg's avatar
Jody Goldberg committed
460 461 462 463
 *   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.
 */
464
static gboolean
465
gnm_expr_equal (GnmExpr const *a, GnmExpr const *b)
Jody Goldberg's avatar
Jody Goldberg committed
466 467 468 469 470 471 472
{
	if (a == b)
		return TRUE;

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

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

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

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

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

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

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

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

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

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

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

	return FALSE;
}

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

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

	return corner;
}

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

566
		ei.pos = pos;
567
		ei.func_call = &expr->func;
568
		v = function_call_with_exprs (&ei, flags);
569 570

		if (v != NULL) {
Jody Goldberg's avatar
Jody Goldberg committed
571 572
			if (v->type == VALUE_CELLRANGE) {
				*res = v->v_range.cell;
573 574 575 576 577 578 579 580
				failed = FALSE;
			}
			value_release (v);
		}
		return failed;
	}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	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
	}
763
	return value_new_error (ep, _("Internal type error"));
764 765
}

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

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
783
	if (a != NULL && VALUE_IS_ERROR (a))
784
		return value_dup (a);
Morten Welinder's avatar
Try!  
Morten Welinder committed
785
	if (b != NULL && VALUE_IS_ERROR (b))
786
		return value_dup (b);
Jody Goldberg's avatar
Jody Goldberg committed
787
	if (VALUE_IS_EMPTY (a))
788
		a = va = (GnmValue *)value_zero;
789
	else if (VALUE_IS_STRING (a)) {
790 791 792 793 794 795 796 797
		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
798
	if (VALUE_IS_EMPTY (b))
799
		b = vb = (GnmValue *)value_zero;
800
	else if (VALUE_IS_STRING (b)) {
801 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
		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
827
	if (a != NULL && VALUE_IS_ERROR (a))
828
		return value_dup (a);
Morten Welinder's avatar
Try!  
Morten Welinder committed
829
	if (b != NULL && VALUE_IS_ERROR (b))
830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849
		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
850
	GnmEvalPos const *ep;
851 852 853
	GnmValue *res;
	GnmValue const *a, *b;
	BinOpImplicitIteratorFunc	func;
854 855 856 857 858 859 860 861

	/* multiply by 0 in unused dimensions.
	 * this is simpler than lots of conditions
	 * 	state->use_x.a ? x : 0
	 **/
	struct {
		int a, b;
	} x, y;
862 863 864 865
	gpointer	user_data;
} BinOpImplicitIteratorState;

static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
866 867
cb_implicit_iter_a_and_b (GnmValueIter const *v_iter,
			  BinOpImplicitIteratorState const *state)
868
{
Jody Goldberg's avatar
Jody Goldberg committed
869 870 871 872 873 874 875 876 877
	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);
878 879 880
	return NULL;
}
static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
881 882
cb_implicit_iter_a_to_scalar_b (GnmValueIter const *v_iter,
				BinOpImplicitIteratorState const *state)
883
{
Jody Goldberg's avatar
Jody Goldberg committed
884 885 886
	state->res->v_array.vals [v_iter->x][v_iter->y] =
		(*state->func) (v_iter->ep,
			v_iter->v, state->b, state->user_data);
887 888
	return NULL;
}
889 890 891 892 893 894 895 896 897 898 899 900

/* 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;
	
	/* a must be a cellrange or array, it can not be NULL */
Jody Goldberg's avatar
Jody Goldberg committed
901
	iter_info.ep   = ep;
902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933
	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
934
			(GnmValueIterFunc) cb_implicit_iter_a_and_b, &iter_info);
935 936 937 938 939
	} 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
940
			(GnmValueIterFunc) cb_implicit_iter_a_to_scalar_b, &iter_info);
941 942 943 944 945 946 947 948
	}

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

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

	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
976
		(GnmValueIterFunc) cb_implicit_iter_b_to_scalar_a, &iter_info);
977 978
	if (a != NULL)
		value_release (a);
979 980
	value_release (b);

981 982 983
	return iter_info.res;
}

984
static GnmValue *
985
negate_value (GnmValue const *v)
986
{
987 988 989 990
	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;
991
	} else
992 993 994 995
		return NULL;
}

static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
996
cb_iter_unary_neg (GnmValueIter const *v_iter, GnmValue *res)
997
{
Jody Goldberg's avatar
Jody Goldberg committed
998
	GnmValue const *v = v_iter->v;
999 1000 1001 1002
	GnmValue *tmp = NULL;

	if (VALUE_IS_EMPTY (v))
		tmp = value_new_int (0);
Morten Welinder's avatar
Try!  
Morten Welinder committed
1003
	else if (VALUE_IS_ERROR (v))
1004
		tmp = value_dup (v);
1005
	else if (VALUE_IS_STRING (v)) {
Jody Goldberg's avatar
Jody Goldberg committed
1006 1007 1008
		GnmValue *conv = format_match_number (
			value_peek_string (v), NULL,
			workbook_date_conv (v_iter->ep->sheet->workbook));
1009 1010 1011 1012
		if (conv != NULL) {
			tmp = negate_value (conv);
			value_release (conv);
		}
1013 1014
	} else {
		/* BOOL goes here.  */
1015
		tmp = negate_value (v);
1016
	}
1017

Jody Goldberg's avatar
Jody Goldberg committed
1018 1019 1020
	if (NULL == tmp)
		tmp = value_new_error_VALUE (v_iter->ep);
	res->v_array.vals[v_iter->x][v_iter->y] = tmp;
1021 1022 1023 1024
	return NULL;
}

static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
1025
cb_iter_percentage (GnmValueIter const *v_iter, GnmValue *res)
1026
{
Jody Goldberg's avatar
Jody Goldberg committed
1027
	GnmValue const *v = v_iter->v;
1028
	GnmValue *tmp;
1029 1030 1031

	if (VALUE_IS_EMPTY (v))
		tmp = value_new_int (0);
Morten Welinder's avatar
Try!  
Morten Welinder committed
1032
	else if (VALUE_IS_ERROR (v))
1033
		tmp = value_dup (v);
1034 1035
	else {
		GnmValue *conv = NULL;
1036
		if (VALUE_IS_STRING (v)) {
Jody Goldberg's avatar
Jody Goldberg committed
1037 1038 1039
			conv = format_match_number (
				value_peek_string (v), NULL,
				workbook_date_conv (v_iter->ep->sheet->workbook));
1040 1041 1042 1043 1044 1045
			if (conv != NULL)
				v = conv;
		}

		if (VALUE_IS_NUMBER (v)){
			tmp = value_new_float (value_get_as_float (v) / 100);
1046
			value_set_fmt (tmp, go_format_default_percentage ());
1047
		} else
Jody Goldberg's avatar
Jody Goldberg committed
1048
			tmp = value_new_error_VALUE (v_iter->ep);
1049

1050
		if (conv != NULL)
1051
			value_release (conv);
1052 1053
	}

Jody Goldberg's avatar
Jody Goldberg committed
1054
	res->v_array.vals[v_iter->x][v_iter->y] = tmp;
1055
	return NULL;
1056 1057
}

Jody Goldberg's avatar
Jody Goldberg committed
1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070
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);

1071 1072
	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
1073

1074
	if (GNM_EXPR_GET_OPER (expr) != GNM_EXPR_OP_INTERSECT)
Jody Goldberg's avatar
Jody Goldberg committed
1075 1076 1077 1078 1079
		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);
1080
	dependent_add_dynamic_dep (ep->dep, &res->v_range.cell);
Jody Goldberg's avatar
Jody Goldberg committed
1081 1082 1083 1084 1085 1086 1087 1088 1089
	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;
}

1090 1091 1092 1093 1094 1095 1096 1097
/**
 * 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.
1098
 **/
Jody Goldberg's avatar
Jody Goldberg committed
1099
GnmValue *
Morten Welinder's avatar
Morten Welinder committed
1100
gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos,
1101
	       GnmExprEvalFlags flags)
Arturo Espinosa's avatar
Arturo Espinosa committed
1102
{
Jody Goldberg's avatar
Jody Goldberg committed
1103
	GnmValue *res = NULL, *a = NULL, *b = NULL;
1104

Jody Goldberg's avatar