expr.c 55.2 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"
39
#include "workbook.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 58 59 60 61 62 63 64 65
/*
 * 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.  */
static gnm_mem_chunk *expression_pool;
#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
80 81
GnmExpr const *
gnm_expr_new_constant (Value *v)
82
{
83
	GnmExprConstant *ans;
84

85
	ans = CHUNK_ALLOC (GnmExprConstant, expression_pool);
86 87
	if (!ans)
		return NULL;
88
	gnm_expr_constant_init (ans, v);
89

90
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
91 92
}

Jody Goldberg's avatar
Jody Goldberg committed
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
/***************************************************************************/

#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

112 113
GnmExpr const *
gnm_expr_new_funcall (FunctionDefinition *func, GnmExprList *args)
114
{
115
	GnmExprFunction *ans;
Jody Goldberg's avatar
Jody Goldberg committed
116
	g_return_val_if_fail (func, NULL);
117

118
	ans = CHUNK_ALLOC (GnmExprFunction, expression_pool);
119 120
	if (!ans)
		return NULL;
121

122
	ans->ref_count = 1;
123
	ans->oper = GNM_EXPR_OP_FUNCALL;
Jody Goldberg's avatar
Jody Goldberg committed
124
	func_ref (func);
Jody Goldberg's avatar
Jody Goldberg committed
125
	ans->func = func;;
126 127
	ans->arg_list = args;

128
	return (GnmExpr *)ans;
129
}
130

Jody Goldberg's avatar
Jody Goldberg committed
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
/***************************************************************************/

#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

148 149
GnmExpr const *
gnm_expr_new_unary  (GnmExprOp op, GnmExpr const *e)
Morten Welinder's avatar
Morten Welinder committed
150
{
151
	GnmExprUnary *ans;
Morten Welinder's avatar
Morten Welinder committed
152

153
	ans = CHUNK_ALLOC (GnmExprUnary, expression_pool);
154 155 156 157
	if (!ans)
		return NULL;

	ans->ref_count = 1;
158
	ans->oper = op;
159
	ans->value = e;
160

161
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
162 163
}

Jody Goldberg's avatar
Jody Goldberg committed
164 165 166 167 168 169 170 171 172 173 174
/***************************************************************************/

#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
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);
182 183
	if (!ans)
		return NULL;
184

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

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

Jody Goldberg's avatar
Jody Goldberg committed
193 194 195 196 197 198 199 200 201 202
/***************************************************************************/

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

203 204
GnmExpr const *
gnm_expr_new_name (GnmNamedExpr *name,
205
		   Sheet *optional_scope, Workbook *optional_wb_scope)
Morten Welinder's avatar
Morten Welinder committed
206
{
207
	GnmExprName *ans;
Morten Welinder's avatar
Morten Welinder committed
208

209
	ans = CHUNK_ALLOC (GnmExprName, expression_pool);
210 211
	if (!ans)
		return NULL;
212

213
	ans->ref_count = 1;
214
	ans->oper = GNM_EXPR_OP_NAME;
215
	ans->name = name;
216
	expr_name_ref (name);
217

218 219 220
	ans->optional_scope = optional_scope;
	ans->optional_wb_scope = optional_wb_scope;

221
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
222
}
223

Jody Goldberg's avatar
Jody Goldberg committed
224 225 226 227 228 229 230 231 232
/***************************************************************************/

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

233 234
GnmExpr const *
gnm_expr_new_cellref (CellRef const *cr)
235
{
236
	GnmExprCellRef *ans;
237

238
	ans = CHUNK_ALLOC (GnmExprCellRef, expression_pool);
239 240
	if (!ans)
		return NULL;
241

242
	ans->ref_count = 1;
243
	ans->oper = GNM_EXPR_OP_CELLREF;
244 245
	ans->ref = *cr;

246
	return (GnmExpr *)ans;
247 248
}

Jody Goldberg's avatar
Jody Goldberg committed
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
/***************************************************************************/

#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.
 **/
268
GnmExpr const *
Jody Goldberg's avatar
Jody Goldberg committed
269
gnm_expr_new_array (int x, int y, int cols, int rows, GnmExpr const *expr)
270
{
271
	GnmExprArray *ans;
272

273
	ans = CHUNK_ALLOC (GnmExprArray, expression_pool);
274 275
	if (ans == NULL)
		return NULL;
276

277
	ans->ref_count = 1;
278
	ans->oper = GNM_EXPR_OP_ARRAY;
279 280 281 282
	ans->x = x;
	ans->y = y;
	ans->rows = rows;
	ans->cols = cols;
283
	ans->corner.value = NULL;
Jody Goldberg's avatar
Jody Goldberg committed
284
	ans->corner.expr = expr;
285
	return (GnmExpr *)ans;
286 287
}

Jody Goldberg's avatar
Jody Goldberg committed
288 289 290 291 292 293 294 295 296 297 298 299 300 301
/***************************************************************************/

#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

302 303
GnmExpr const *
gnm_expr_new_set (GnmExprList *set)
304
{
305
	GnmExprSet *ans;
306

307
	ans = CHUNK_ALLOC (GnmExprSet, expression_pool);
308 309
	if (!ans)
		return NULL;
310

311
	ans->ref_count = 1;
312
	ans->oper = GNM_EXPR_OP_SET;
313
	ans->set = set;
314

315
	return (GnmExpr *)ans;
316 317
}

Jody Goldberg's avatar
Jody Goldberg committed
318 319
/***************************************************************************/

320 321 322
/**
 * gnm_expr_ref:
 * Increments the ref_count for an expression node.
Arturo Espinosa's avatar
Arturo Espinosa committed
323
 */
324
void
325
gnm_expr_ref (GnmExpr const *expr)
326
{
327 328
	g_return_if_fail (expr != NULL);
	g_return_if_fail (expr->any.ref_count > 0);
329

330
	((GnmExpr *)expr)->any.ref_count++;
Arturo Espinosa's avatar
Arturo Espinosa committed
331 332 333
}

static void
334
do_gnm_expr_unref (GnmExpr const *expr)
Arturo Espinosa's avatar
Arturo Espinosa committed
335
{
336
	if (--((GnmExpr *)expr)->any.ref_count > 0)
Morten Welinder's avatar
Morten Welinder committed
337 338
		return;

339
	switch (expr->any.oper) {
340 341 342 343
	case GNM_EXPR_OP_RANGE_CTOR:
	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
344
		break;
345

346 347
	case GNM_EXPR_OP_FUNCALL:
		gnm_expr_list_unref (expr->func.arg_list);
348
		func_unref (expr->func.func);
Arturo Espinosa's avatar
Arturo Espinosa committed
349 350
		break;

351
	case GNM_EXPR_OP_NAME:
352
		expr_name_unref (expr->name.name);
Michael Meeks's avatar
Michael Meeks committed
353 354
		break;

355 356 357 358 359
	case GNM_EXPR_OP_CONSTANT:
		value_release ((Value *)expr->constant.value);
		break;

	case GNM_EXPR_OP_CELLREF:
Arturo Espinosa's avatar
Arturo Espinosa committed
360 361
		break;

362 363
	case GNM_EXPR_OP_ANY_UNARY:
		do_gnm_expr_unref (expr->unary.value);
Arturo Espinosa's avatar
Arturo Espinosa committed
364
		break;
365

366
	case GNM_EXPR_OP_ARRAY:
367 368 369
		if (expr->array.x == 0 && expr->array.y == 0) {
			if (expr->array.corner.value)
				value_release (expr->array.corner.value);
370
			do_gnm_expr_unref (expr->array.corner.expr);
371
		}
Jody Goldberg's avatar
Jody Goldberg committed
372
		break;
373

374 375
	case GNM_EXPR_OP_SET:
		gnm_expr_list_unref (expr->set.set);
376
		break;
377
	default:
378
		g_warning ("do_gnm_expr_unref error.");
379
		break;
Arturo Espinosa's avatar
Arturo Espinosa committed
380
	}
381

382
	CHUNK_FREE (expression_pool, (gpointer)expr);
383 384
}

Morten Welinder's avatar
Morten Welinder committed
385
/*
386 387
 * gnm_expr_unref:
 * Decrements the ref_count for part of a expression.  (All trees are expected
Morten Welinder's avatar
Morten Welinder committed
388 389 390
 * 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.)
 */
391
void
392
gnm_expr_unref (GnmExpr const *expr)
393
{
394 395
	g_return_if_fail (expr != NULL);
	g_return_if_fail (expr->any.ref_count > 0);
396

397
	if (expr->any.ref_count == 1)
398
		do_gnm_expr_unref (expr);
399
	else
400
		((GnmExpr *)expr)->any.ref_count--;
401 402
}

Jody Goldberg's avatar
Jody Goldberg committed
403
/**
404
 * gnm_expr_is_shared : Returns TRUE if the reference count
Jody Goldberg's avatar
Jody Goldberg committed
405 406 407
 *   for the supplied expression is > 1
 */
gboolean
408
gnm_expr_is_shared (GnmExpr const *expr)
Jody Goldberg's avatar
Jody Goldberg committed
409
{
410
	g_return_val_if_fail (expr != NULL, FALSE);
Jody Goldberg's avatar
Jody Goldberg committed
411

412
	return (expr->any.ref_count > 1);
Jody Goldberg's avatar
Jody Goldberg committed
413 414
}

Jody Goldberg's avatar
Jody Goldberg committed
415
/**
416
 * gnm_expr_equal : Returns TRUE if the supplied expressions are exactly the
Jody Goldberg's avatar
Jody Goldberg committed
417 418 419 420 421
 *   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
422
gnm_expr_equal (GnmExpr const *a, GnmExpr const *b)
Jody Goldberg's avatar
Jody Goldberg committed
423 424 425 426 427 428 429 430 431 432 433
{
	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) {
434
	case GNM_EXPR_OP_RANGE_CTOR:
435 436 437
	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
438

439 440
	case GNM_EXPR_OP_ANY_UNARY:
		return gnm_expr_equal (a->unary.value, b->unary.value);
Jody Goldberg's avatar
Jody Goldberg committed
441

442
	case GNM_EXPR_OP_FUNCALL:
443
		return (a->func.func == b->func.func) &&
444
			gnm_expr_list_equal (a->func.arg_list, b->func.arg_list);
Jody Goldberg's avatar
Jody Goldberg committed
445

446
	case GNM_EXPR_OP_NAME:
Jody Goldberg's avatar
Jody Goldberg committed
447 448
		return a->name.name == b->name.name;

449 450
	case GNM_EXPR_OP_CELLREF:
		return cellref_equal (&a->cellref.ref, &b->cellref.ref);
Jody Goldberg's avatar
Jody Goldberg committed
451

452
	case GNM_EXPR_OP_CONSTANT: {
Jody Goldberg's avatar
Jody Goldberg committed
453 454 455 456 457 458 459 460 461 462 463 464 465
		Value const *va = a->constant.value;
		Value const *vb = b->constant.value;

		if (va->type != vb->type)
			return FALSE;

		if (va->type == VALUE_CELLRANGE)
			return	cellref_equal (&va->v_range.cell.a, &vb->v_range.cell.a) &&
				cellref_equal (&va->v_range.cell.b, &vb->v_range.cell.b);

		return value_compare (va, vb, TRUE) == IS_EQUAL;
	}

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

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

477 478
	case GNM_EXPR_OP_SET:
		return gnm_expr_list_equal (a->set.set, b->set.set);
479

Jody Goldberg's avatar
Jody Goldberg committed
480 481 482 483 484 485 486
	default :
		g_assert_not_reached ();
	}

	return FALSE;
}

487
/**
488
 * gnm_expr_array_intersection :
489 490 491 492 493 494 495 496 497 498 499 500 501
 * @v: a VALUE_ARRAY
 *
 * Returns the upper left corner of an array.
 *
 * Always release the value passed in.
 *
 * FIXME FIXME FIXME : This will need to be reworked
 * cellrange for array expressions
 *
 * Return value:
 *     duplicate of the value in the upper left of the array
 **/
Value *
502
gnm_expr_array_intersection (Value *a)
503
{
Morten Welinder's avatar
Typo.  
Morten Welinder committed
504
	Value *tmp = value_duplicate (a->v_array.vals[0][0]);
505 506 507 508
	value_release (a);
	return tmp;
}

Jody Goldberg's avatar
Jody Goldberg committed
509 510
static Value *
cb_range_eval (Sheet *sheet, int col, int row, Cell *cell, void *ignore)
511
{
Jody Goldberg's avatar
Jody Goldberg committed
512 513
	cell_eval (cell);
	return NULL;
514 515
}

516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534
static Cell *
expr_array_corner (GnmExpr const *expr,
			Sheet const *sheet, CellPos const *pos)
{
	Cell *corner = sheet_cell_get (sheet,
		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
535 536
gnm_expr_extract_ref (CellRef *res, GnmExpr const *expr,
		      EvalPos const *pos, GnmExprEvalFlags flags)
537 538 539 540 541 542 543 544 545
{
	switch (expr->any.oper) {
	case GNM_EXPR_OP_FUNCALL : {
		gboolean failed = TRUE;
		Value *v;
		FunctionEvalInfo ei;
		ei.pos = pos;
		ei.func_call = (GnmExprFunction const *)expr;

546
		v = function_call_with_list (&ei, expr->func.arg_list, flags);
547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574
		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: {
		Value const *v = expr->constant.value;
		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:
		if (!expr->name.name->active || expr->name.name->builtin)
			return TRUE;
575
		return gnm_expr_extract_ref (res, expr->name.name->t.expr_tree, pos, flags);
576 577 578 579 580 581
	default :
		break;
	}
	return TRUE;
}

582
static Value *
583 584
expr_eval_real (GnmExpr const *expr, EvalPos const *pos,
		GnmExprEvalFlags flags)
Arturo Espinosa's avatar
Arturo Espinosa committed
585
{
586
	Value *res = NULL, *a = NULL, *b = NULL;
587

588
	g_return_val_if_fail (expr != NULL, NULL);
589
	g_return_val_if_fail (pos != NULL, NULL);
590

591
	switch (expr->any.oper){
592 593 594 595 596 597
	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:
	case GNM_EXPR_OP_LTE: {
598
		ValueCompare comp;
599

600
		a = expr_eval_real (expr->binary.value_a, pos, flags);
Jody Goldberg's avatar
Jody Goldberg committed
601 602
		if (a != NULL) {
			if (a->type == VALUE_CELLRANGE) {
603
				a = value_intersection (a, pos);
Jody Goldberg's avatar
Jody Goldberg committed
604
				if (a == NULL)
605
					return value_new_error (pos, gnumeric_err_VALUE);
606
			} else if (a->type == VALUE_ARRAY) {
607
				a = gnm_expr_array_intersection (a);
608 609
				if (a == NULL)
					return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
610 611 612
			} else if (a->type == VALUE_ERROR)
				return a;
		}
Morten Welinder's avatar
Morten Welinder committed
613

614
		b = expr_eval_real (expr->binary.value_b, pos, flags);
Jody Goldberg's avatar
Jody Goldberg committed
615 616 617
		if (b != NULL) {
			Value *res = NULL;
			if (b->type == VALUE_CELLRANGE) {
618
				b = value_intersection (b, pos);
Jody Goldberg's avatar
Jody Goldberg committed
619
				if (b == NULL)
620
					res = value_new_error (pos, gnumeric_err_VALUE);
621
			} else if (b->type == VALUE_ARRAY) {
622
				b = gnm_expr_array_intersection (b);
623 624
				if (b == NULL)
					return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
625 626 627 628 629 630 631 632
			} else if (b->type == VALUE_ERROR)
				res = b;

			if (res != NULL) {
				if (a != NULL)
					value_release (a);
				return res;
			}
Morten Welinder's avatar
Morten Welinder committed
633
		}
634

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

637 638 639 640
		if (a != NULL)
			value_release (a);
		if (b != NULL)
			value_release (b);
641

Michael Meeks's avatar
Michael Meeks committed
642
		if (comp == TYPE_MISMATCH) {
643 644 645 646
			/* TODO TODO TODO : Make error more informative
			 *    regarding what is comparing to what
			 */
			/* For equality comparisons even errors are ok */
647
			if (expr->any.oper == GNM_EXPR_OP_EQUAL)
648
				return value_new_bool (FALSE);
649
			if (expr->any.oper == GNM_EXPR_OP_NOT_EQUAL)
650 651
				return value_new_bool (TRUE);

652
			return value_new_error (pos, gnumeric_err_VALUE);
653
		}
654

655
		switch (expr->any.oper) {
656
		case GNM_EXPR_OP_EQUAL:
657
			res = value_new_bool (comp == IS_EQUAL);
Arturo Espinosa's avatar
Arturo Espinosa committed
658 659
			break;

660
		case GNM_EXPR_OP_GT:
661
			res = value_new_bool (comp == IS_GREATER);
Arturo Espinosa's avatar
Arturo Espinosa committed
662 663
			break;

664
		case GNM_EXPR_OP_LT:
665
			res = value_new_bool (comp == IS_LESS);
Arturo Espinosa's avatar
Arturo Espinosa committed
666 667
			break;

668
		case GNM_EXPR_OP_NOT_EQUAL:
669
			res = value_new_bool (comp != IS_EQUAL);
Arturo Espinosa's avatar
Arturo Espinosa committed
670 671
			break;

672
		case GNM_EXPR_OP_LTE:
673
			res = value_new_bool (comp != IS_GREATER);
Arturo Espinosa's avatar
Arturo Espinosa committed
674 675
			break;

676
		case GNM_EXPR_OP_GTE:
677
			res = value_new_bool (comp != IS_LESS);
Arturo Espinosa's avatar
Arturo Espinosa committed
678
			break;
679

Arturo Espinosa's avatar
Arturo Espinosa committed
680
		default:
681
			g_assert_not_reached ();
682
			res = value_new_error (pos,
683
						_("Internal type error"));
Arturo Espinosa's avatar
Arturo Espinosa committed
684
		}
Morten Welinder's avatar
Morten Welinder committed
685
		return res;
Arturo Espinosa's avatar
Arturo Espinosa committed
686
	}
687

688 689 690 691 692
	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:
693 694 695 696 697 698 699 700 701
		/*
		 * 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
		 */

702
	        /* Guarantees a != NULL */
703 704
		a = gnm_expr_eval (expr->binary.value_a, pos,
			       flags & (~GNM_EXPR_EVAL_PERMIT_EMPTY));
Jody Goldberg's avatar
Jody Goldberg committed
705 706 707

		/* Handle implicit intersection */
		if (a->type == VALUE_CELLRANGE) {
708
			a = value_intersection (a, pos);
Jody Goldberg's avatar
Jody Goldberg committed
709
			if (a == NULL)
710
				return value_new_error (pos, gnumeric_err_VALUE);
711
		} else if (a->type == VALUE_ARRAY) {
712
			a = gnm_expr_array_intersection (a);
713 714
			if (a == NULL)
				return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
715 716
		}

717 718
		/* 1) Error from A */
		if (a->type == VALUE_ERROR)
719
			return value_error_set_pos (&a->v_err, pos);
720

721
		/* 2) #!VALUE error if A is not a number */
722
		if (a->type == VALUE_STRING) {
723
			Value *tmp = format_match_number (a->v_str.val->str, NULL);
724 725 726 727 728 729

			value_release (a);
			if (tmp == NULL)
				return value_new_error (pos, gnumeric_err_VALUE);
			a = tmp;
		} else if (!VALUE_IS_NUMBER (a)) {
730
			value_release (a);
731
			return value_new_error (pos, gnumeric_err_VALUE);
732 733
		}

734
	        /* Guarantees that b != NULL */
735 736
		b = gnm_expr_eval (expr->binary.value_b, pos,
			       flags & (~GNM_EXPR_EVAL_PERMIT_EMPTY));
Arturo Espinosa's avatar
Arturo Espinosa committed
737

Jody Goldberg's avatar
Jody Goldberg committed
738 739
		/* Handle implicit intersection */
		if (b->type == VALUE_CELLRANGE) {
740
			b = value_intersection (a, pos);
Jody Goldberg's avatar
Jody Goldberg committed
741
			if (b == NULL)
742
				return value_new_error (pos, gnumeric_err_VALUE);
743
		} else if (b->type == VALUE_ARRAY) {
744
			b = gnm_expr_array_intersection (b);
745 746
			if (b == NULL)
				return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
747 748
		}

749 750
		/* 3) Error from B */
		if (b->type == VALUE_ERROR) {
751
			value_release (a);
752
			return value_error_set_pos (&b->v_err, pos);
Arturo Espinosa's avatar
Arturo Espinosa committed
753
		}
754

755
		/* 4) #!VALUE error if B is not a number */
756
		if (b->type == VALUE_STRING) {
757
			Value *tmp = format_match_number (b->v_str.val->str, NULL);
758 759 760 761 762 763 764 765

			value_release (b);
			if (tmp == NULL) {
				value_release (a);
				return value_new_error (pos, gnumeric_err_VALUE);
			}
			b = tmp;
		} else if (!VALUE_IS_NUMBER (b)) {
766 767
			value_release (a);
			value_release (b);
768
			return value_new_error (pos, gnumeric_err_VALUE);
Arturo Espinosa's avatar
Arturo Espinosa committed
769
		}
770

771
		if (a->type != VALUE_FLOAT && b->type != VALUE_FLOAT){
Morten Welinder's avatar
Morten Welinder committed
772
			int ia = value_get_as_int (a);
773
			int ib = value_get_as_int (b);
774
			gnum_float dres;
775 776
			int ires;

Morten Welinder's avatar
Morten Welinder committed
777 778
			value_release (a);
			value_release (b);
779

780 781
			/* FIXME: we could use simple (cheap) heuristics to
			   catch most cases where overflow will not happen.  */
782
			switch (expr->any.oper){
783
			case GNM_EXPR_OP_ADD:
784
				dres = (gnum_float)ia + (gnum_float)ib;
Morten Welinder's avatar
Morten Welinder committed
785
				break;
786

787
			case GNM_EXPR_OP_SUB:
788
				dres = (gnum_float)ia - (gnum_float)ib;
Morten Welinder's avatar
Morten Welinder committed
789
				break;
790

791
			case GNM_EXPR_OP_MULT:
792
				dres = (gnum_float)ia * (gnum_float)ib;
Morten Welinder's avatar
Morten Welinder committed
793
				break;
Arturo Espinosa's avatar
Arturo Espinosa committed
794

795
			case GNM_EXPR_OP_DIV:
796
				if (ib == 0)
797
					return value_new_error (pos, gnumeric_err_DIV0);
798
				dres = (gnum_float)ia / (gnum_float)ib;
Morten Welinder's avatar
Morten Welinder committed
799
				break;
800

801
			case GNM_EXPR_OP_EXP:
802
				if (ia == 0 && ib <= 0)
803
					return value_new_error (pos, gnumeric_err_NUM);
804
				dres = powgnum ((gnum_float)ia, (gnum_float)ib);
805 806
				if (!finitegnum (dres))
					return value_new_error (pos, gnumeric_err_NUM);
Morten Welinder's avatar
Morten Welinder committed
807
				break;
808

Arturo Espinosa's avatar
Arturo Espinosa committed
809
			default:
810
				abort ();
Arturo Espinosa's avatar
Arturo Espinosa committed
811
			}
Morten Welinder's avatar
Morten Welinder committed
812 813 814 815 816 817

			ires = (int)dres;
			if (dres == ires)
				return value_new_int (ires);
			else
				return value_new_float (dres);
Arturo Espinosa's avatar
Arturo Espinosa committed
818
		} else {
819 820
			gnum_float const va = value_get_as_float (a);
			gnum_float const vb = value_get_as_float (b);
821 822
			value_release (a);
			value_release (b);
823

824
			switch (expr->any.oper){
825
			case GNM_EXPR_OP_ADD:
Arturo Espinosa's avatar
Arturo Espinosa committed
826
				return value_new_float (va + vb);
827

828
			case GNM_EXPR_OP_SUB:
Arturo Espinosa's avatar
Arturo Espinosa committed
829
				return value_new_float (va - vb);
830

831
			case GNM_EXPR_OP_MULT:
Arturo Espinosa's avatar
Arturo Espinosa committed
832
				return value_new_float (va * vb);
833

834
			case GNM_EXPR_OP_DIV:
835
				return (vb == 0.0)
836
				    ? value_new_error (pos,
837
						       gnumeric_err_DIV0)
Arturo Espinosa's avatar
Arturo Espinosa committed
838
				    : value_new_float (va / vb);
839

840 841
			case GNM_EXPR_OP_EXP: {
				gnum_float res;
842 843
				if ((va == 0 && vb <= 0) ||
				    (va < 0 && vb != (int)vb))
844
					return value_new_error (pos, gnumeric_err_NUM);
845 846 847 848 849 850

				res = powgnum (va, vb);
				return finitegnum (res)
					? value_new_float (res)
					: value_new_error (pos, gnumeric_err_NUM);
			}
851

Arturo Espinosa's avatar
Arturo Espinosa committed
852
			default:
853
				break;
Arturo Espinosa's avatar
Arturo Espinosa committed
854 855
			}
		}
856
		return value_new_error (pos, _("Unknown operator"));
857

858 859 860
	case GNM_EXPR_OP_PERCENTAGE:
	case GNM_EXPR_OP_UNARY_NEG:
	case GNM_EXPR_OP_UNARY_PLUS:
861
	        /* Garantees that a != NULL */
862 863
		a = gnm_expr_eval (expr->unary.value, pos,
			flags & (~GNM_EXPR_EVAL_PERMIT_EMPTY));
Jody Goldberg's avatar
Jody Goldberg committed
864 865 866

		/* Handle implicit intersection */
		if (a->type == VALUE_CELLRANGE) {
867
			a = value_intersection (a, pos);
Jody Goldberg's avatar
Jody Goldberg committed
868
			if (a == NULL)
869
				return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
870
		} else if (a->type == VALUE_ARRAY) {
871
			a = gnm_expr_array_intersection (a);
872 873
			if (a == NULL)
				return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
874 875
		}

876 877
		if (a->type == VALUE_ERROR)
			return a;
Jody Goldberg's avatar
Jody Goldberg committed
878

879
		if (expr->any.oper == GNM_EXPR_OP_UNARY_PLUS)
Jody Goldberg's avatar
Jody Goldberg committed
880 881
			return a;

882 883
		if (!VALUE_IS_NUMBER (a)){
			value_release (a);
884
			return value_new_error (pos, gnumeric_err_VALUE);
885
		}
886
		if (expr->any.oper == GNM_EXPR_OP_UNARY_NEG) {
Jody Goldberg's avatar
Jody Goldberg committed
887
			if (a->type == VALUE_INTEGER)
888
				res = value_new_int (-a->v_int.val);
Jody Goldberg's avatar
Jody Goldberg committed
889
			else if (a->type == VALUE_FLOAT)
890
				res = value_new_float (-a->v_float.val);
Jody Goldberg's avatar
Jody Goldberg committed
891
			else
892
				res = value_new_bool (!a->v_float.val);
893 894 895 896 897
			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
898
			res = value_new_float (value_get_as_float (a) / 100);
899 900 901
			VALUE_FMT (res) = style_format_default_percentage ();
			style_format_ref (VALUE_FMT (res));
		}
902
		value_release (a);
Morten Welinder's avatar
Morten Welinder committed
903
		return res;
904

905
	case GNM_EXPR_OP_CAT:
906
		a = expr_eval_real (expr->binary.value_a, pos, flags);
907
		if (a != NULL && a->type == VALUE_ERROR)
908
			return a;
909
		b = expr_eval_real (expr->binary.value_b, pos, flags);
910 911 912
		if (b != NULL && b->type == VALUE_ERROR) {
			if (a != NULL)
				value_release (a);
913
			return b;
914 915
		}

916 917 918 919 920 921 922 923 924 925 926 927
		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);
928
			res = value_new_string_nocopy (tmp);
Morten Welinder's avatar
Morten Welinder committed
929 930
			value_release (a);
			value_release (b);
931 932
		}

Morten Welinder's avatar
Morten Welinder committed
933
		return res;
Arturo Espinosa's avatar
Arturo Espinosa committed
934

935
	case GNM_EXPR_OP_FUNCALL: {
936 937
		FunctionEvalInfo ei;
		ei.pos = pos;
938
		ei.func_call = (GnmExprFunction const *)expr;
939
		return function_call_with_list (&ei, expr->func.arg_list, flags);
940
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
941

942
	case GNM_EXPR_OP_NAME:
943 944 945
		if (expr->name.name->active)
			return expr_name_eval (expr->name.name, pos, flags);
		return value_new_error (pos, gnumeric_err_REF);
Michael Meeks's avatar
Michael Meeks committed
946