expr.c 55.5 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 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
	case GNM_EXPR_OP_RANGE_CTOR:
341
	case GNM_EXPR_OP_INTERSECT:
342 343 344
	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
345
		break;
346

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

454
	case GNM_EXPR_OP_CONSTANT: {
Jody Goldberg's avatar
Jody Goldberg committed
455 456 457 458 459 460 461 462 463 464 465 466 467
		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;
	}

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;
}

Jody Goldberg's avatar
Jody Goldberg committed
486 487
static Value *
cb_range_eval (Sheet *sheet, int col, int row, Cell *cell, void *ignore)
488
{
Jody Goldberg's avatar
Jody Goldberg committed
489 490
	cell_eval (cell);
	return NULL;
491 492
}

493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511
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
512 513
gnm_expr_extract_ref (CellRef *res, GnmExpr const *expr,
		      EvalPos const *pos, GnmExprEvalFlags flags)
514 515 516 517 518 519 520 521 522
{
	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;

523
		v = function_call_with_list (&ei, expr->func.arg_list, flags);
524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
		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;
552
		return gnm_expr_extract_ref (res, expr->name.name->t.expr_tree, pos, flags);
553 554 555 556 557 558
	default :
		break;
	}
	return TRUE;
}

Jody Goldberg's avatar
Jody Goldberg committed
559
static inline Value *
560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585
handle_empty (Value *res, GnmExprEvalFlags flags)
{
	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;
}

/**
 * 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.
 */
Value *
gnm_expr_eval (GnmExpr const *expr, EvalPos const *pos,
	       GnmExprEvalFlags flags)
Arturo Espinosa's avatar
Arturo Espinosa committed
586
{
587
	Value *res = NULL, *a = NULL, *b = NULL;
588

589 590
	g_return_val_if_fail (expr != NULL, handle_empty (NULL, flags));
	g_return_val_if_fail (pos != NULL, handle_empty (NULL, flags));
591

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

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

612 613
		b = gnm_expr_eval (expr->binary.value_b, pos,
				   flags | GNM_EXPR_EVAL_PERMIT_EMPTY);
Jody Goldberg's avatar
Jody Goldberg committed
614 615
		if (b != NULL) {
			Value *res = NULL;
616
			if (b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY) {
617
				b = value_intersection (b, pos);
Jody Goldberg's avatar
Jody Goldberg committed
618
				if (b == NULL)
619
					res = value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
620 621 622 623 624 625
			} else if (b->type == VALUE_ERROR)
				res = b;

			if (res != NULL) {
				if (a != NULL)
					value_release (a);
626
				return handle_empty (res, flags);
Jody Goldberg's avatar
Jody Goldberg committed
627
			}
Morten Welinder's avatar
Morten Welinder committed
628
		}
629

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

632 633 634 635
		if (a != NULL)
			value_release (a);
		if (b != NULL)
			value_release (b);
636

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

647
			return value_new_error (pos, gnumeric_err_VALUE);
648
		}
649

650
		switch (expr->any.oper) {
651
		case GNM_EXPR_OP_EQUAL:
652
			res = value_new_bool (comp == IS_EQUAL);
Arturo Espinosa's avatar
Arturo Espinosa committed
653 654
			break;

655
		case GNM_EXPR_OP_GT:
656
			res = value_new_bool (comp == IS_GREATER);
Arturo Espinosa's avatar
Arturo Espinosa committed
657 658
			break;

659
		case GNM_EXPR_OP_LT:
660
			res = value_new_bool (comp == IS_LESS);
Arturo Espinosa's avatar
Arturo Espinosa committed
661 662
			break;

663
		case GNM_EXPR_OP_NOT_EQUAL:
664
			res = value_new_bool (comp != IS_EQUAL);
Arturo Espinosa's avatar
Arturo Espinosa committed
665 666
			break;

667
		case GNM_EXPR_OP_LTE:
668
			res = value_new_bool (comp != IS_GREATER);
Arturo Espinosa's avatar
Arturo Espinosa committed
669 670
			break;

671
		case GNM_EXPR_OP_GTE:
672
			res = value_new_bool (comp != IS_LESS);
Arturo Espinosa's avatar
Arturo Espinosa committed
673
			break;
674

Arturo Espinosa's avatar
Arturo Espinosa committed
675
		default:
676
			g_assert_not_reached ();
677
			res = value_new_error (pos,
678
						_("Internal type error"));
Arturo Espinosa's avatar
Arturo Espinosa committed
679
		}
Morten Welinder's avatar
Morten Welinder committed
680
		return res;
Arturo Espinosa's avatar
Arturo Espinosa committed
681
	}
682

683 684 685 686 687
	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:
688 689 690 691 692 693 694 695 696
		/*
		 * 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
		 */

697
	        /* Guarantees a != NULL */
698
		a = gnm_expr_eval (expr->binary.value_a, pos,
699
				   flags & (~GNM_EXPR_EVAL_PERMIT_EMPTY));
Jody Goldberg's avatar
Jody Goldberg committed
700 701

		/* Handle implicit intersection */
702
		if (a->type == VALUE_CELLRANGE || a->type == VALUE_ARRAY) {
703
			a = value_intersection (a, pos);
Jody Goldberg's avatar
Jody Goldberg committed
704
			if (a == NULL)
705
				return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
706 707
		}

708 709
		/* 1) Error from A */
		if (a->type == VALUE_ERROR)
710
			return value_error_set_pos (&a->v_err, pos);
711

712
		/* 2) #!VALUE error if A is not a number */
713
		if (a->type == VALUE_STRING) {
714
			Value *tmp = format_match_number (a->v_str.val->str, NULL);
715 716 717 718 719 720

			value_release (a);
			if (tmp == NULL)
				return value_new_error (pos, gnumeric_err_VALUE);
			a = tmp;
		} else if (!VALUE_IS_NUMBER (a)) {
721
			value_release (a);
722
			return value_new_error (pos, gnumeric_err_VALUE);
723 724
		}

725
	        /* Guarantees that b != NULL */
726
		b = gnm_expr_eval (expr->binary.value_b, pos,
727
				   flags & (~GNM_EXPR_EVAL_PERMIT_EMPTY));
Arturo Espinosa's avatar
Arturo Espinosa committed
728

Jody Goldberg's avatar
Jody Goldberg committed
729
		/* Handle implicit intersection */
730
		if (b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY) {
731
			b = value_intersection (a, pos);
Jody Goldberg's avatar
Jody Goldberg committed
732
			if (b == NULL)
733
				return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
734 735
		}

736 737
		/* 3) Error from B */
		if (b->type == VALUE_ERROR) {
738
			value_release (a);
739
			return value_error_set_pos (&b->v_err, pos);
Arturo Espinosa's avatar
Arturo Espinosa committed
740
		}
741

742
		/* 4) #!VALUE error if B is not a number */
743
		if (b->type == VALUE_STRING) {
744
			Value *tmp = format_match_number (b->v_str.val->str, NULL);
745 746 747 748 749 750 751 752

			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)) {
753 754
			value_release (a);
			value_release (b);
755
			return value_new_error (pos, gnumeric_err_VALUE);
Arturo Espinosa's avatar
Arturo Espinosa committed
756
		}
757

758
		if (a->type != VALUE_FLOAT && b->type != VALUE_FLOAT){
Morten Welinder's avatar
Morten Welinder committed
759
			int ia = value_get_as_int (a);
760
			int ib = value_get_as_int (b);
761
			gnum_float dres;
762 763
			int ires;

Morten Welinder's avatar
Morten Welinder committed
764 765
			value_release (a);
			value_release (b);
766

767 768
			/* FIXME: we could use simple (cheap) heuristics to
			   catch most cases where overflow will not happen.  */
769
			switch (expr->any.oper){
770
			case GNM_EXPR_OP_ADD:
771
				dres = (gnum_float)ia + (gnum_float)ib;
Morten Welinder's avatar
Morten Welinder committed
772
				break;
773

774
			case GNM_EXPR_OP_SUB:
775
				dres = (gnum_float)ia - (gnum_float)ib;
Morten Welinder's avatar
Morten Welinder committed
776
				break;
777

778
			case GNM_EXPR_OP_MULT:
779
				dres = (gnum_float)ia * (gnum_float)ib;
Morten Welinder's avatar
Morten Welinder committed
780
				break;
Arturo Espinosa's avatar
Arturo Espinosa committed
781

782
			case GNM_EXPR_OP_DIV:
783
				if (ib == 0)
784
					return value_new_error (pos, gnumeric_err_DIV0);
785
				dres = (gnum_float)ia / (gnum_float)ib;
Morten Welinder's avatar
Morten Welinder committed
786
				break;
787

788
			case GNM_EXPR_OP_EXP:
789
				if (ia == 0 && ib <= 0)
790
					return value_new_error (pos, gnumeric_err_NUM);
791
				dres = powgnum ((gnum_float)ia, (gnum_float)ib);
792 793
				if (!finitegnum (dres))
					return value_new_error (pos, gnumeric_err_NUM);
Morten Welinder's avatar
Morten Welinder committed
794
				break;
795

Arturo Espinosa's avatar
Arturo Espinosa committed
796
			default:
797
				abort ();
Arturo Espinosa's avatar
Arturo Espinosa committed
798
			}
Morten Welinder's avatar
Morten Welinder committed
799 800 801 802 803 804

			ires = (int)dres;
			if (dres == ires)
				return value_new_int (ires);
			else
				return value_new_float (dres);
Arturo Espinosa's avatar
Arturo Espinosa committed
805
		} else {
806 807
			gnum_float const va = value_get_as_float (a);
			gnum_float const vb = value_get_as_float (b);
808 809
			value_release (a);
			value_release (b);
810

811
			switch (expr->any.oper){
812
			case GNM_EXPR_OP_ADD:
Arturo Espinosa's avatar
Arturo Espinosa committed
813
				return value_new_float (va + vb);
814

815
			case GNM_EXPR_OP_SUB:
Arturo Espinosa's avatar
Arturo Espinosa committed
816
				return value_new_float (va - vb);
817

818
			case GNM_EXPR_OP_MULT:
Arturo Espinosa's avatar
Arturo Espinosa committed
819
				return value_new_float (va * vb);
820

821
			case GNM_EXPR_OP_DIV:
822
				return (vb == 0.0)
823
				    ? value_new_error (pos,
824
						       gnumeric_err_DIV0)
Arturo Espinosa's avatar
Arturo Espinosa committed
825
				    : value_new_float (va / vb);
826

827 828
			case GNM_EXPR_OP_EXP: {
				gnum_float res;
829 830
				if ((va == 0 && vb <= 0) ||
				    (va < 0 && vb != (int)vb))
831
					return value_new_error (pos, gnumeric_err_NUM);
832 833 834 835 836 837

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

Arturo Espinosa's avatar
Arturo Espinosa committed
839
			default:
840
				break;
Arturo Espinosa's avatar
Arturo Espinosa committed
841 842
			}
		}
843
		return value_new_error (pos, _("Unknown operator"));
844

845 846 847
	case GNM_EXPR_OP_PERCENTAGE:
	case GNM_EXPR_OP_UNARY_NEG:
	case GNM_EXPR_OP_UNARY_PLUS:
848
	        /* Garantees that a != NULL */
849
		a = gnm_expr_eval (expr->unary.value, pos,
850
				   flags & (~GNM_EXPR_EVAL_PERMIT_EMPTY));
Jody Goldberg's avatar
Jody Goldberg committed
851 852

		/* Handle implicit intersection */
853
		if (a->type == VALUE_CELLRANGE || a->type == VALUE_ARRAY) {
854
			a = value_intersection (a, pos);
Jody Goldberg's avatar
Jody Goldberg committed
855
			if (a == NULL)
856
				return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
857 858
		}

859 860
		if (a->type == VALUE_ERROR)
			return a;
Jody Goldberg's avatar
Jody Goldberg committed
861

862
		if (expr->any.oper == GNM_EXPR_OP_UNARY_PLUS)
Jody Goldberg's avatar
Jody Goldberg committed
863 864
			return a;

865 866
		if (!VALUE_IS_NUMBER (a)){
			value_release (a);
867
			return value_new_error (pos, gnumeric_err_VALUE);
868
		}
869
		if (expr->any.oper == GNM_EXPR_OP_UNARY_NEG) {
Jody Goldberg's avatar
Jody Goldberg committed
870
			if (a->type == VALUE_INTEGER)
871
				res = value_new_int (-a->v_int.val);
Jody Goldberg's avatar
Jody Goldberg committed
872
			else if (a->type == VALUE_FLOAT)
873
				res = value_new_float (-a->v_float.val);
Jody Goldberg's avatar
Jody Goldberg committed
874
			else
875
				res = value_new_bool (!a->v_float.val);
876 877 878 879 880
			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
881
			res = value_new_float (value_get_as_float (a) / 100);
882 883 884
			VALUE_FMT (res) = style_format_default_percentage ();
			style_format_ref (VALUE_FMT (res));
		}
885
		value_release (a);
Morten Welinder's avatar
Morten Welinder committed
886
		return res;
887

888
	case GNM_EXPR_OP_CAT:
889 890 891
#warning BUG does not support intersection
		a = gnm_expr_eval (expr->binary.value_a, pos,
				   flags | GNM_EXPR_EVAL_PERMIT_EMPTY);
892
		if (a != NULL && a->type == VALUE_ERROR)
893
			return a;
894 895
		b = gnm_expr_eval (expr->binary.value_b, pos,
				   flags | GNM_EXPR_EVAL_PERMIT_EMPTY);
896 897 898
		if (b != NULL && b->type == VALUE_ERROR) {
			if (a != NULL)
				value_release (a);
899
			return b;
900 901
		}

902 903 904 905 906 907 908 909 910 911 912 913
		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);
914
			res = value_new_string_nocopy (tmp);
Morten Welinder's avatar
Morten Welinder committed
915 916
			value_release (a);
			value_release (b);
917 918
		}

Morten Welinder's avatar
Morten Welinder committed
919
		return res;
Arturo Espinosa's avatar
Arturo Espinosa committed
920

921
	case GNM_EXPR_OP_FUNCALL: {
922 923
		FunctionEvalInfo ei;
		ei.pos = pos;
924
		ei.func_call = (GnmExprFunction const *)expr;
925
		return handle_empty (function_call_with_list (&ei, expr->func.arg_list, flags), flags);
926
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
927

928
	case GNM_EXPR_OP_NAME:
929
		if (expr->name.name->active)
930
			return handle_empty (expr_name_eval (expr->name.name, pos, flags), flags);
931
		return value_new_error (pos, gnumeric_err_REF);
Michael Meeks's avatar
Michael Meeks committed
932

933 934
	case GNM_EXPR_OP_CELLREF: {
		CellRef const * const ref = &expr->cellref.ref;
Arturo Espinosa's avatar
Arturo Espinosa committed
935
		Cell *cell;
936
		CellPos dest;
937

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

940 941
		cell = sheet_cell_get (eval_sheet (ref->sheet, pos->sheet),
			dest.col, dest.row);
942
		if (cell == NULL)
943
			return handle_empty (NULL, flags);
944