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

expr.c 60.7 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 19 20
 *
 * 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
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
Miguel de Icaza's avatar
Miguel de Icaza committed
21
 */
22
#include <gnumeric-config.h>
Zbigniew Chyla's avatar
New  
Zbigniew Chyla committed
23
#include <gnumeric-i18n.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"
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
30
#include "format.h"
31
#include "func.h"
Jody Goldberg's avatar
Jody Goldberg committed
32
#include "cell.h"
Jody Goldberg's avatar
Jody Goldberg committed
33 34
#include "sheet.h"
#include "str.h"
35
#include "value.h"
36
#include "parse-util.h"
37
#include "ranges.h"
38
#include "number-match.h"
Jody Goldberg's avatar
Jody Goldberg committed
39
#include "workbook-priv.h"
Jeffrey Stedfast's avatar
Jeffrey Stedfast committed
40
#include "gutils.h"
41
#include "parse-util.h"
42
#include "mathfunc.h"
43

44 45
#include <math.h>
#include <string.h>
Jody Goldberg's avatar
Jody Goldberg committed
46
#include <stdlib.h>
47

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
/* Memory pool for expressions.  */
Jody Goldberg's avatar
Jody Goldberg committed
58
static GnmMemChunk *expression_pool;
59 60 61 62 63 64 65
#define CHUNK_ALLOC(T,p) ((T*)gnm_mem_chunk_alloc (p))
#define CHUNK_FREE(p,v) gnm_mem_chunk_free ((p), (v))
#else
#define CHUNK_ALLOC(T,c) g_new (T,1)
#define CHUNK_FREE(p,v) g_free ((v))
#endif

66 67
/***************************************************************************/

Jody Goldberg's avatar
Jody Goldberg committed
68 69 70 71 72 73 74 75 76 77 78 79
#if 0
static guint
gnm_expr_constant_hash (GnmExprConstant const *expr)
{
	return value_hash (expr->value);
}
static gboolean
gnm_expr_constant_eq (GnmExprConstant const *a,
		      GnmExprConstant const *b)
{
}
#endif
Jody Goldberg's avatar
Jody Goldberg committed
80 81 82 83 84 85
/**
 * gnm_expr_new_constant :
 * @v :
 *
 * Absorbs the value.
 **/
86
GnmExpr const *
Jody Goldberg's avatar
Jody Goldberg committed
87
gnm_expr_new_constant (GnmValue *v)
88
{
89
	GnmExprConstant *ans;
90

91
	ans = CHUNK_ALLOC (GnmExprConstant, expression_pool);
92 93
	if (!ans)
		return NULL;
94
	gnm_expr_constant_init (ans, v);
95

96
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
97 98
}

Jody Goldberg's avatar
Jody Goldberg committed
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
/***************************************************************************/

#if 0
static guint
gnm_expr_function_hash (GnmExprFunction const *expr)
{
	guint h = expr->oper;
	GnmExprList *l;
	for (l = expr->arg_list; l; l = l->next)
		h = (h * 3) ^ (GPOINTER_TO_INT (l->data));
	return h;
}
static gboolean
gnm_expr_function_eq (GnmExprFunction const *a,
		      GnmExprFunction const *b)
{
}
#endif

118
GnmExpr const *
Jody Goldberg's avatar
Jody Goldberg committed
119
gnm_expr_new_funcall (GnmFunc *func, GnmExprList *args)
120
{
121
	GnmExprFunction *ans;
Jody Goldberg's avatar
Jody Goldberg committed
122
	g_return_val_if_fail (func, NULL);
123

124
	ans = CHUNK_ALLOC (GnmExprFunction, expression_pool);
125 126
	if (!ans)
		return NULL;
127

128
	ans->ref_count = 1;
129
	ans->oper = GNM_EXPR_OP_FUNCALL;
Jody Goldberg's avatar
Jody Goldberg committed
130
	gnm_func_ref (func);
Jody Goldberg's avatar
Jody Goldberg committed
131
	ans->func = func;;
132 133
	ans->arg_list = args;

134
	return (GnmExpr *)ans;
135
}
136

Jody Goldberg's avatar
Jody Goldberg committed
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
/***************************************************************************/

#if 0
static guint
gnm_expr_unary_hash (GnmExprUnary const *expr)
{
	return  (GPOINTER_TO_INT (expr->value) * 7) ^
		(guint)(expr->oper);
}
static gboolean
gnm_expr_unary_eq (GnmExprUnary const *a,
		   GnmExprUnary const *b)
{
	return  a->oper == b->oper && a->value == b->value;
}
#endif

154 155
GnmExpr const *
gnm_expr_new_unary  (GnmExprOp op, GnmExpr const *e)
Morten Welinder's avatar
Morten Welinder committed
156
{
157
	GnmExprUnary *ans;
Morten Welinder's avatar
Morten Welinder committed
158

159
	ans = CHUNK_ALLOC (GnmExprUnary, expression_pool);
160 161 162 163
	if (!ans)
		return NULL;

	ans->ref_count = 1;
164
	ans->oper = op;
165
	ans->value = e;
166

167
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
168 169
}

Jody Goldberg's avatar
Jody Goldberg committed
170 171 172 173 174 175 176 177 178 179 180
/***************************************************************************/

#if 0
static guint
gnm_expr_binary_hash (GnmExprBinary const *expr)
{
	return  (GPOINTER_TO_INT (expr->value_a) * 7) ^
		(GPOINTER_TO_INT (expr->value_b) * 3) ^
		(guint)(expr->oper);
}
#endif
Morten Welinder's avatar
Morten Welinder committed
181

182 183
GnmExpr const *
gnm_expr_new_binary (GnmExpr const *l, GnmExprOp op, GnmExpr const *r)
Morten Welinder's avatar
Morten Welinder committed
184
{
185
	GnmExprBinary *ans;
Morten Welinder's avatar
Morten Welinder committed
186

187
	ans = CHUNK_ALLOC (GnmExprBinary, expression_pool);
188 189
	if (!ans)
		return NULL;
190

191
	ans->ref_count = 1;
192
	ans->oper = op;
193 194
	ans->value_a = l;
	ans->value_b = r;
195

196
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
197 198
}

Jody Goldberg's avatar
Jody Goldberg committed
199 200 201 202 203 204 205 206 207 208
/***************************************************************************/

#if 0
static guint
gnm_expr_name_hash (GnmExprName const *expr)
{
	return GPOINTER_TO_INT (expr->name);
}
#endif

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

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

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

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

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

Jody Goldberg's avatar
Jody Goldberg committed
230 231 232 233 234 235 236 237 238
/***************************************************************************/

#if 0
static guint
gnm_expr_cellref_hash (GnmExprCellRef const *expr)
{
}
#endif

239
GnmExpr const *
Jody Goldberg's avatar
Jody Goldberg committed
240
gnm_expr_new_cellref (GnmCellRef const *cr)
241
{
242
	GnmExprCellRef *ans;
243

244
	ans = CHUNK_ALLOC (GnmExprCellRef, expression_pool);
245 246
	if (!ans)
		return NULL;
247

248
	ans->ref_count = 1;
249
	ans->oper = GNM_EXPR_OP_CELLREF;
250 251
	ans->ref = *cr;

252
	return (GnmExpr *)ans;
253 254
}

Jody Goldberg's avatar
Jody Goldberg committed
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
/***************************************************************************/

#if 0
static guint
gnm_expr_array_hash (GnmExprArray const *expr)
{
}
#endif

/**
 * gnm_expr_new_array :
 * @x :
 * @y :
 * @cols :
 * @rows :
 * @expr : optionally NULL.
 *
 * Absorb a referernce to @expr if it is non NULL.
 **/
274
GnmExpr const *
Jody Goldberg's avatar
Jody Goldberg committed
275
gnm_expr_new_array (int x, int y, int cols, int rows, GnmExpr const *expr)
276
{
277
	GnmExprArray *ans;
278

279
	ans = CHUNK_ALLOC (GnmExprArray, expression_pool);
280 281
	if (ans == NULL)
		return NULL;
282

283
	ans->ref_count = 1;
284
	ans->oper = GNM_EXPR_OP_ARRAY;
285 286 287 288
	ans->x = x;
	ans->y = y;
	ans->rows = rows;
	ans->cols = cols;
289
	ans->corner.value = NULL;
Jody Goldberg's avatar
Jody Goldberg committed
290
	ans->corner.expr = expr;
291
	return (GnmExpr *)ans;
292 293
}

Jody Goldberg's avatar
Jody Goldberg committed
294 295 296 297 298 299 300 301 302 303 304 305 306 307
/***************************************************************************/

#if 0
static guint
gnm_expr_set_hash (GnmExprSet const *expr)
{
	guint h = expr->oper;
	GnmExprList *l;
	for (l = expr->set; l; l = l->next)
		h = (h * 3) ^ (GPOINTER_TO_INT (l->data));
	return h;
}
#endif

308 309
GnmExpr const *
gnm_expr_new_set (GnmExprList *set)
310
{
311
	GnmExprSet *ans;
312

313
	ans = CHUNK_ALLOC (GnmExprSet, expression_pool);
314 315
	if (!ans)
		return NULL;
316

317
	ans->ref_count = 1;
318
	ans->oper = GNM_EXPR_OP_SET;
319
	ans->set = set;
320

321
	return (GnmExpr *)ans;
322 323
}

Jody Goldberg's avatar
Jody Goldberg committed
324 325
/***************************************************************************/

326 327 328
/**
 * gnm_expr_ref:
 * Increments the ref_count for an expression node.
Arturo Espinosa's avatar
Arturo Espinosa committed
329
 */
330
void
331
gnm_expr_ref (GnmExpr const *expr)
332
{
333 334
	g_return_if_fail (expr != NULL);
	g_return_if_fail (expr->any.ref_count > 0);
335

336
	((GnmExpr *)expr)->any.ref_count++;
Arturo Espinosa's avatar
Arturo Espinosa committed
337 338 339
}

static void
340
do_gnm_expr_unref (GnmExpr const *expr)
Arturo Espinosa's avatar
Arturo Espinosa committed
341
{
342
	if (--((GnmExpr *)expr)->any.ref_count > 0)
Morten Welinder's avatar
Morten Welinder committed
343 344
		return;

345
	switch (expr->any.oper) {
346
	case GNM_EXPR_OP_RANGE_CTOR:
347
	case GNM_EXPR_OP_INTERSECT:
348 349 350
	case GNM_EXPR_OP_ANY_BINARY:
		do_gnm_expr_unref (expr->binary.value_a);
		do_gnm_expr_unref (expr->binary.value_b);
Arturo Espinosa's avatar
Arturo Espinosa committed
351
		break;
352

353 354
	case GNM_EXPR_OP_FUNCALL:
		gnm_expr_list_unref (expr->func.arg_list);
Jody Goldberg's avatar
Jody Goldberg committed
355
		gnm_func_unref (expr->func.func);
Arturo Espinosa's avatar
Arturo Espinosa committed
356 357
		break;

358
	case GNM_EXPR_OP_NAME:
359
		expr_name_unref (expr->name.name);
Michael Meeks's avatar
Michael Meeks committed
360 361
		break;

362
	case GNM_EXPR_OP_CONSTANT:
Jody Goldberg's avatar
Jody Goldberg committed
363
		value_release ((GnmValue *)expr->constant.value);
364 365 366
		break;

	case GNM_EXPR_OP_CELLREF:
Arturo Espinosa's avatar
Arturo Espinosa committed
367 368
		break;

369 370
	case GNM_EXPR_OP_ANY_UNARY:
		do_gnm_expr_unref (expr->unary.value);
Arturo Espinosa's avatar
Arturo Espinosa committed
371
		break;
372

373
	case GNM_EXPR_OP_ARRAY:
374 375 376
		if (expr->array.x == 0 && expr->array.y == 0) {
			if (expr->array.corner.value)
				value_release (expr->array.corner.value);
377
			do_gnm_expr_unref (expr->array.corner.expr);
378
		}
Jody Goldberg's avatar
Jody Goldberg committed
379
		break;
380

381 382
	case GNM_EXPR_OP_SET:
		gnm_expr_list_unref (expr->set.set);
383
		break;
384 385

#ifndef DEBUG_SWITCH_ENUM
386
	default:
387
		g_assert_not_reached ();
388
		break;
389
#endif
Arturo Espinosa's avatar
Arturo Espinosa committed
390
	}
391

392
	CHUNK_FREE (expression_pool, (gpointer)expr);
393 394
}

Morten Welinder's avatar
Morten Welinder committed
395
/*
396 397
 * gnm_expr_unref:
 * Decrements the ref_count for part of a expression.  (All trees are expected
Morten Welinder's avatar
Morten Welinder committed
398 399 400
 * to have been created with a ref-count of one, so when we hit zero, we
 * go down over the tree and unref the tree and its leaves stuff.)
 */
401
void
402
gnm_expr_unref (GnmExpr const *expr)
403
{
404 405
	g_return_if_fail (expr != NULL);
	g_return_if_fail (expr->any.ref_count > 0);
406

407
	if (expr->any.ref_count == 1)
408
		do_gnm_expr_unref (expr);
409
	else
410
		((GnmExpr *)expr)->any.ref_count--;
411 412
}

Jody Goldberg's avatar
Jody Goldberg committed
413
/**
414
 * gnm_expr_is_shared : Returns TRUE if the reference count
Jody Goldberg's avatar
Jody Goldberg committed
415 416 417
 *   for the supplied expression is > 1
 */
gboolean
418
gnm_expr_is_shared (GnmExpr const *expr)
Jody Goldberg's avatar
Jody Goldberg committed
419
{
420
	g_return_val_if_fail (expr != NULL, FALSE);
Jody Goldberg's avatar
Jody Goldberg committed
421

422
	return (expr->any.ref_count > 1);
Jody Goldberg's avatar
Jody Goldberg committed
423 424
}

Jody Goldberg's avatar
Jody Goldberg committed
425
/**
426
 * gnm_expr_equal : Returns TRUE if the supplied expressions are exactly the
Jody Goldberg's avatar
Jody Goldberg committed
427 428 429 430 431
 *   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.
 */
gboolean
432
gnm_expr_equal (GnmExpr const *a, GnmExpr const *b)
Jody Goldberg's avatar
Jody Goldberg committed
433 434 435 436 437 438 439 440 441 442 443
{
	if (a == b)
		return TRUE;

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

	if (a->any.oper != b->any.oper)
		return FALSE;

	switch (a->any.oper) {
444
	case GNM_EXPR_OP_RANGE_CTOR:
445
	case GNM_EXPR_OP_INTERSECT:
446 447 448
	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
449

450 451
	case GNM_EXPR_OP_ANY_UNARY:
		return gnm_expr_equal (a->unary.value, b->unary.value);
Jody Goldberg's avatar
Jody Goldberg committed
452

453
	case GNM_EXPR_OP_FUNCALL:
454
		return (a->func.func == b->func.func) &&
455
			gnm_expr_list_equal (a->func.arg_list, b->func.arg_list);
Jody Goldberg's avatar
Jody Goldberg committed
456

457
	case GNM_EXPR_OP_NAME:
458 459 460
		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
461

462 463
	case GNM_EXPR_OP_CELLREF:
		return cellref_equal (&a->cellref.ref, &b->cellref.ref);
Jody Goldberg's avatar
Jody Goldberg committed
464

465 466
	case GNM_EXPR_OP_CONSTANT:
		return value_equal (a->constant.value, b->constant.value);
Jody Goldberg's avatar
Jody Goldberg committed
467

468 469 470
	case GNM_EXPR_OP_ARRAY: {
		GnmExprArray const *aa = &a->array;
		GnmExprArray const *ab = &b->array;
Jody Goldberg's avatar
Jody Goldberg committed
471 472 473 474 475

		return	aa->cols == ab->cols &&
			aa->rows == ab->rows &&
			aa->x == ab->x &&
			aa->y == ab->y &&
476
			gnm_expr_equal (aa->corner.expr, ab->corner.expr);
Jody Goldberg's avatar
Jody Goldberg committed
477 478
	}

479 480
	case GNM_EXPR_OP_SET:
		return gnm_expr_list_equal (a->set.set, b->set.set);
Jody Goldberg's avatar
Jody Goldberg committed
481 482 483 484 485
	}

	return FALSE;
}

486
static GnmCell *
487
expr_array_corner (GnmExpr const *expr,
Jody Goldberg's avatar
Jody Goldberg committed
488
		   Sheet const *sheet, GnmCellPos const *pos)
489
{
490
	GnmCell *corner = sheet_cell_get (sheet,
491 492 493 494 495 496 497 498 499 500 501 502 503 504
		pos->col - expr->array.x, pos->row - expr->array.y);

	/* 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);
	g_return_val_if_fail (corner->base.expression != (void *)0xdeadbeef, NULL);
	g_return_val_if_fail (corner->base.expression->any.oper == GNM_EXPR_OP_ARRAY, NULL);
	g_return_val_if_fail (corner->base.expression->array.x == 0, NULL);
	g_return_val_if_fail (corner->base.expression->array.y == 0, NULL);

	return corner;
}

static gboolean
Jody Goldberg's avatar
Jody Goldberg committed
505
gnm_expr_extract_ref (GnmCellRef *res, GnmExpr const *expr,
506
		      EvalPos const *pos, GnmExprEvalFlags flags)
507 508 509 510
{
	switch (expr->any.oper) {
	case GNM_EXPR_OP_FUNCALL : {
		gboolean failed = TRUE;
Jody Goldberg's avatar
Jody Goldberg committed
511
		GnmValue *v;
512 513 514 515
		FunctionEvalInfo ei;
		ei.pos = pos;
		ei.func_call = (GnmExprFunction const *)expr;

516
		v = function_call_with_list (&ei, expr->func.arg_list, flags);
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532
		if (v != NULL) {
			if (v->type == VALUE_CELLRANGE &&
			    cellref_equal (&v->v_range.cell.a, &v->v_range.cell.b)) {
				*res = v->v_range.cell.a;
				failed = FALSE;
			}
			value_release (v);
		}
		return failed;
	}

	case GNM_EXPR_OP_CELLREF :
		*res = expr->cellref.ref;
		return FALSE;

	case GNM_EXPR_OP_CONSTANT: {
Jody Goldberg's avatar
Jody Goldberg committed
533
		GnmValue const *v = expr->constant.value;
534 535 536 537 538 539 540 541 542
		if (v->type == VALUE_CELLRANGE &&
		    cellref_equal (&v->v_range.cell.a, &v->v_range.cell.b)) {
			*res = v->v_range.cell.a;
			return FALSE;
		}
		return TRUE;
	}

	case GNM_EXPR_OP_NAME:
543
		if (!expr->name.name->active)
544
			return TRUE;
545
		return gnm_expr_extract_ref (res, expr->name.name->expr, pos, flags);
546 547 548 549 550 551
	default :
		break;
	}
	return TRUE;
}

Jody Goldberg's avatar
Jody Goldberg committed
552 553
static inline GnmValue *
handle_empty (GnmValue *res, GnmExprEvalFlags flags)
554 555 556 557 558 559 560 561 562 563 564 565 566
{
	if (res == NULL)
		return (flags & GNM_EXPR_EVAL_PERMIT_EMPTY)
		    ? NULL : value_new_int (0);

	if (res->type == VALUE_EMPTY) {
		value_release (res);
		return (flags & GNM_EXPR_EVAL_PERMIT_EMPTY)
		    ? NULL : value_new_int (0);
	}
	return res;
}

Jody Goldberg's avatar
Jody Goldberg committed
567 568 569
/**
 * value_intersection :
 * @v   : a VALUE_CELLRANGE
Morten Welinder's avatar
Morten Welinder committed
570
 * @pos :
Jody Goldberg's avatar
Jody Goldberg committed
571 572 573 574 575 576 577 578 579 580 581 582 583 584 585
 *
 * 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
586 587
static GnmValue *
value_intersection (GnmValue *v, EvalPos const *pos)
Jody Goldberg's avatar
Jody Goldberg committed
588
{
Jody Goldberg's avatar
Jody Goldberg committed
589 590
	GnmValue *res = NULL;
	GnmRange r;
Jody Goldberg's avatar
Jody Goldberg committed
591 592 593 594
	Sheet *start_sheet, *end_sheet;
	gboolean found = FALSE;

	if (v->type == VALUE_ARRAY) {
595
		res = value_dup (v->v_array.vals[0][0]);
Jody Goldberg's avatar
Jody Goldberg committed
596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630
		value_release (v);
		return res;
	}

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

	/* inverted ranges */
	rangeref_normalize (&v->v_range.cell, pos, &start_sheet, &end_sheet, &r);
	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) {
631
			GnmCell *cell = sheet_cell_get (
Jody Goldberg's avatar
Jody Goldberg committed
632 633 634 635 636
				eval_sheet (start_sheet, pos->sheet),
				col, row);
			if (cell == NULL)
				return value_new_empty ();
			cell_eval (cell);
637
			return value_dup (cell->value);
Jody Goldberg's avatar
Jody Goldberg committed
638 639 640
		}
	}

641
	return value_new_error_VALUE (pos);
Jody Goldberg's avatar
Jody Goldberg committed
642 643
}
#if 0
Jody Goldberg's avatar
Jody Goldberg committed
644
static GnmValue *
645
cb_range_eval (Sheet *sheet, int col, int row, GnmCell *cell, void *ignore)
Jody Goldberg's avatar
Jody Goldberg committed
646 647 648 649 650 651
{
	cell_eval (cell);
	return NULL;
}
#endif

Jody Goldberg's avatar
Jody Goldberg committed
652
static GnmValue *
653
bin_cmp (GnmExprOp op, GnmValDiff comp, EvalPos const *pos)
654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685
{
	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);

		return value_new_error_VALUE (pos);
	}

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

#ifdef NOT_READY_YET
/* args will be 'EE' */
Jody Goldberg's avatar
Jody Goldberg committed
686 687
static GnmValue *
func_bin_cmp (FunctionEvalInfo *ei, GnmValue *argv [])
688 689 690 691 692 693 694 695 696 697
{
	if (argv[0]->type == VALUE_ERROR)
		return argv[0];
	if (argv[0]->type == VALUE_ERROR)
		return argv[1];
	return bin_cmp (expr->any.oper, 
		value_compare (argv[0], argv[1], FALSE), ei->pos);
}
#endif

698 699 700 701 702 703 704 705 706
/**
 * 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.
 */
Jody Goldberg's avatar
Jody Goldberg committed
707
GnmValue *
708 709
gnm_expr_eval (GnmExpr const *expr, EvalPos const *pos,
	       GnmExprEvalFlags flags)
Arturo Espinosa's avatar
Arturo Espinosa committed
710
{
Jody Goldberg's avatar
Jody Goldberg committed
711
	GnmValue *res = NULL, *a = NULL, *b = NULL;
712
	GnmValDiff comp;
713

714 715
	g_return_val_if_fail (expr != NULL, handle_empty (NULL, flags));
	g_return_val_if_fail (pos != NULL, handle_empty (NULL, flags));
716

717
	switch (expr->any.oper){
718 719 720 721 722
	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:
723
	case GNM_EXPR_OP_LTE:
Jody Goldberg's avatar
Jody Goldberg committed
724
		flags = (flags | GNM_EXPR_EVAL_PERMIT_EMPTY) & ~GNM_EXPR_EVAL_PERMIT_NON_SCALAR;
Morten Welinder's avatar
Morten Welinder committed
725

Jody Goldberg's avatar
Jody Goldberg committed
726 727 728 729 730 731 732 733 734
		a = gnm_expr_eval (expr->binary.value_a, pos, flags);
		if (a != NULL && a->type == VALUE_ERROR)
			return a;

		b = gnm_expr_eval (expr->binary.value_b, pos, flags);
		if (b != NULL && b->type == VALUE_ERROR) {
			if (a != NULL)
				value_release (a);
			return b;
Morten Welinder's avatar
Morten Welinder committed
735
		}
736

JP Rosevear's avatar
JP Rosevear committed
737
		comp = value_compare (a, b, FALSE);
Arturo Espinosa's avatar
Arturo Espinosa committed
738

739 740 741 742
		if (a != NULL)
			value_release (a);
		if (b != NULL)
			value_release (b);
743

744
		return bin_cmp (expr->any.oper, comp, pos);
745

746 747 748 749 750
	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:
751 752 753 754 755 756 757 758 759
		/*
		 * 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
760 761
	        /* Guarantees value != NULL */
		flags &= ~(GNM_EXPR_EVAL_PERMIT_EMPTY | GNM_EXPR_EVAL_PERMIT_NON_SCALAR);
Jody Goldberg's avatar
Jody Goldberg committed
762

763
		/* 1) Error from A */
Jody Goldberg's avatar
Jody Goldberg committed
764
		a = gnm_expr_eval (expr->binary.value_a, pos, flags);
765
		if (a->type == VALUE_ERROR)
766
			return value_error_set_pos (&a->v_err, pos);
767

768
		/* 2) #!VALUE error if A is not a number */
769
		if (a->type == VALUE_STRING) {
Jody Goldberg's avatar
Jody Goldberg committed
770
			GnmValue *tmp = format_match_number (a->v_str.val->str, NULL,
771
				workbook_date_conv (pos->sheet->workbook));
772 773 774

			value_release (a);
			if (tmp == NULL)
775
				return value_new_error_VALUE (pos);
776 777
			a = tmp;
		} else if (!VALUE_IS_NUMBER (a)) {
778
			value_release (a);
779
			return value_new_error_VALUE (pos);
780 781 782
		}

		/* 3) Error from B */
Jody Goldberg's avatar
Jody Goldberg committed
783
		b = gnm_expr_eval (expr->binary.value_b, pos, flags);
784
		if (b->type == VALUE_ERROR) {
785
			value_release (a);
786
			return value_error_set_pos (&b->v_err, pos);
Arturo Espinosa's avatar
Arturo Espinosa committed
787
		}
788

789
		/* 4) #!VALUE error if B is not a number */
790
		if (b->type == VALUE_STRING) {
Jody Goldberg's avatar
Jody Goldberg committed
791
			GnmValue *tmp = format_match_number (b->v_str.val->str, NULL,
792
				workbook_date_conv (pos->sheet->workbook));
793 794 795 796

			value_release (b);
			if (tmp == NULL) {
				value_release (a);
797
				return value_new_error_VALUE (pos);
798 799 800
			}
			b = tmp;
		} else if (!VALUE_IS_NUMBER (b)) {
801 802
			value_release (a);
			value_release (b);
803
			return value_new_error_VALUE (pos);
Arturo Espinosa's avatar
Arturo Espinosa committed
804
		}
805

806
		if (a->type != VALUE_FLOAT && b->type != VALUE_FLOAT){
Morten Welinder's avatar
Morten Welinder committed
807
			int ia = value_get_as_int (a);
808
			int ib = value_get_as_int (b);
Jody Goldberg's avatar
Jody Goldberg committed
809
			gnm_float dres;
810 811
			int ires;

Morten Welinder's avatar
Morten Welinder committed
812 813
			value_release (a);
			value_release (b);
814

815 816
			/* FIXME: we could use simple (cheap) heuristics to
			   catch most cases where overflow will not happen.  */
817
			switch (expr->any.oper){
818
			case GNM_EXPR_OP_ADD:
Jody Goldberg's avatar
Jody Goldberg committed
819
				dres = (gnm_float)ia + (gnm_float)ib;
Morten Welinder's avatar
Morten Welinder committed
820
				break;
821

822
			case GNM_EXPR_OP_SUB:
Jody Goldberg's avatar
Jody Goldberg committed
823
				dres = (gnm_float)ia - (gnm_float)ib;
Morten Welinder's avatar
Morten Welinder committed
824
				break;
825

826
			case GNM_EXPR_OP_MULT:
Jody Goldberg's avatar
Jody Goldberg committed
827
				dres = (gnm_float)ia * (gnm_float)ib;
Morten Welinder's avatar
Morten Welinder committed
828
				break;
Arturo Espinosa's avatar
Arturo Espinosa committed
829

830
			case GNM_EXPR_OP_DIV:
831
				if (ib == 0)
832
					return value_new_error_DIV0 (pos);
Jody Goldberg's avatar
Jody Goldberg committed
833
				dres = (gnm_float)ia / (gnm_float)ib;
Morten Welinder's avatar
Morten Welinder committed
834
				break;
835

836
			case GNM_EXPR_OP_EXP:
837
				if (ia == 0 && ib <= 0)
838
					return value_new_error_NUM (pos);
Jody Goldberg's avatar
Jody Goldberg committed
839
				dres = powgnum ((gnm_float)ia, (gnm_float)ib);
840
				if (!finitegnum (dres))
841
					return value_new_error_NUM (pos);
Morten Welinder's avatar
Morten Welinder committed
842
				break;
843

Arturo Espinosa's avatar
Arturo Espinosa committed
844
			default:
845
				abort ();
Arturo Espinosa's avatar
Arturo Espinosa committed
846
			}
Morten Welinder's avatar
Morten Welinder committed
847 848 849 850 851 852

			ires = (int)dres;
			if (dres == ires)
				return value_new_int (ires);
			else
				return value_new_float (dres);
Arturo Espinosa's avatar
Arturo Espinosa committed
853
		} else {
Jody Goldberg's avatar
Jody Goldberg committed
854 855
			gnm_float const va = value_get_as_float (a);
			gnm_float const vb = value_get_as_float (b);
856 857
			value_release (a);
			value_release (b);
858

859
			switch (expr->any.oper){
860
			case GNM_EXPR_OP_ADD:
Arturo Espinosa's avatar
Arturo Espinosa committed
861
				return value_new_float (va + vb);
862

863
			case GNM_EXPR_OP_SUB:
Arturo Espinosa's avatar
Arturo Espinosa committed
864
				return value_new_float (va - vb);
865

866
			case GNM_EXPR_OP_MULT:
Arturo Espinosa's avatar
Arturo Espinosa committed
867
				return value_new_float (va * vb);
868

869
			case GNM_EXPR_OP_DIV:
870
				return (vb == 0.0)
871 872
					? value_new_error_DIV0 (pos)
					: value_new_float (va / vb);
873

874
			case GNM_EXPR_OP_EXP: {
Jody Goldberg's avatar
Jody Goldberg committed
875
				gnm_float res;
876 877
				if ((va == 0 && vb <= 0) ||
				    (va < 0 && vb != (int)vb))
878
					return value_new_error_NUM (pos);
879 880 881 882

				res = powgnum (va, vb);
				return finitegnum (res)
					? value_new_float (res)
883
					: value_new_error_NUM (pos);
884
			}
885

Arturo Espinosa's avatar
Arturo Espinosa committed
886
			default:
887
				break;
Arturo Espinosa's avatar
Arturo Espinosa committed
888 889
			}
		}
890
		return value_new_error (pos, _("Unknown operator"));
891

892 893 894
	case GNM_EXPR_OP_PERCENTAGE:
	case GNM_EXPR_OP_UNARY_NEG:
	case GNM_EXPR_OP_UNARY_PLUS:
Jody Goldberg's avatar
Jody Goldberg committed
895 896
	        /* Guarantees value != NULL */
		flags &= ~(GNM_EXPR_EVAL_PERMIT_EMPTY | GNM_EXPR_EVAL_PERMIT_NON_SCALAR);
Jody Goldberg's avatar
Jody Goldberg committed
897

Jody Goldberg's avatar
Jody Goldberg committed
898
		a = gnm_expr_eval (expr->unary.value, pos, flags);
899 900
		if (a->type == VALUE_ERROR)
			return a;
Jody Goldberg's avatar
Jody Goldberg committed
901

902
		if (expr->any.oper == GNM_EXPR_OP_UNARY_PLUS)
Jody Goldberg's avatar
Jody Goldberg committed
903 904
			return a;

905 906
		if (!VALUE_IS_NUMBER (a)){
			value_release (a);
907
			return value_new_error_VALUE (pos);
908
		}
909
		if (expr->any.oper == GNM_EXPR_OP_UNARY_NEG) {
Jody Goldberg's avatar
Jody Goldberg committed
910
			if (a->type == VALUE_INTEGER)
911
				res = value_new_int (-a->v_int.val);
Jody Goldberg's avatar
Jody Goldberg committed
912
			else if (a->type == VALUE_FLOAT)
913
				res = value_new_float (-a->v_float.val);
Jody Goldberg's avatar
Jody Goldberg committed
914
			else
915
				res = value_new_bool (!a->v_float.val);
916 917 918 919 920
			if (VALUE_FMT (a) != NULL) {
				VALUE_FMT (res) = VALUE_FMT (a);
				style_format_ref (VALUE_FMT (res));
			}
		} else {
Morten Welinder's avatar
Morten Welinder committed
921
			res = value_new_float (value_get_as_float (a) / 100);
922 923 924
			VALUE_FMT (res) = style_format_default_percentage ();
			style_format_ref (VALUE_FMT (res));
		}
925
		value_release (a);
Morten Welinder's avatar
Morten Welinder committed
926
		return res;
927

928
	case GNM_EXPR_OP_CAT:
Jody Goldberg's avatar
Jody Goldberg committed
929 930
		flags = (flags | GNM_EXPR_EVAL_PERMIT_EMPTY) & ~GNM_EXPR_EVAL_PERMIT_NON_SCALAR;
		a = gnm_expr_eval (expr->binary.value_a, pos, flags);
931
		if (a != NULL && a->type == VALUE_ERROR)
932
			return a;
Jody Goldberg's avatar
Jody Goldberg committed
933
		b = gnm_expr_eval (expr->binary.value_b, pos, flags);
934 935 936
		if (b != NULL && b->type == VALUE_ERROR) {
			if (a != NULL)
				value_release (a);
937
			return b;
938 939
		}

940 941 942 943 944 945 946 947 948 949 950 951
		if (a == NULL) {
			if (b != NULL) {
				res = value_new_string (value_peek_string (b));
				value_release (b);
			} else
				res = value_new_string ("");
		} else if (b == NULL) {
			res = value_new_string (value_peek_string (a));
			value_release (a);
		} else {
			char *tmp = g_strconcat (value_peek_string (a),
						 value_peek_string (b), NULL);
952
			res = value_new_string_nocopy (tmp);
Morten Welinder's avatar
Morten Welinder committed
953 954
			value_release (a);
			value_release (b);
955 956
		}

Morten Welinder's avatar
Morten Welinder committed
957
		return res;
Arturo Espinosa's avatar
Arturo Espinosa committed
958

959
	case GNM_EXPR_OP_FUNCALL: {
960 961
		FunctionEvalInfo ei;
		ei.pos = pos;
962
		ei.func_call = (GnmExprFunction const *)expr;
Jody Goldberg's avatar
Jody Goldberg committed
963 964 965 966 967 968 969
		res = function_call_with_list (&ei, expr->func.arg_list, flags);
		if (res != NULL && res->type == VALUE_CELLRANGE) {
			dependent_add_dynamic_dep (pos->dep, &res->v_range);
			if (!(flags & GNM_EXPR_EVAL_PERMIT_NON_SCALAR)) {
				res = value_intersection (res, pos);
				return (res != NULL)
					? handle_empty (res, flags)
970
					: value_new_error_VALUE (pos);
Jody Goldberg's avatar
Jody Goldberg committed
971 972 973
			}
			return res;
		}
974 975 976 977
		if (res == NULL)
			return (flags & GNM_EXPR_EVAL_PERMIT_EMPTY)
			    ? NULL : value_new_int (0);
		return res;
978
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
979

980
	case GNM_EXPR_OP_NAME:
981
		if (expr->name.name->active)
982
			return handle_empty (expr_name_eval (expr->name.name, pos, flags), flags);
983
		return value_new_error_REF (pos);
Michael Meeks's avatar
Michael Meeks committed
984

985
	case GNM_EXPR_OP_CELLREF: {
Jody Goldberg's avatar
Jody Goldberg committed
986
		GnmCellRef const * const ref = &expr->cellref.ref;
987
		GnmCell *cell;
Jody Goldberg's avatar
Jody Goldberg committed
988
		GnmCellPos dest;
989

990
		cellref_get_abs_pos (ref, &pos->eval, &dest);
Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
991

992 993
		cell = sheet_cell_get (eval_sheet (ref->sheet, pos->sheet),
			dest.col, dest.row);
994
		if (cell == NULL)
995
			return handle_empty (NULL, flags);
996

Jody Goldberg's avatar
Jody Goldberg committed
997
		cell_eval (cell);