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

expr.c 55.1 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 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 * Copyright (C) 2001-2002 Jody Goldberg (jody@gnome.org)
 *
 * 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
20
 */
21 22
#include <gnumeric-config.h>
#include "gnumeric.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
23
#include "expr.h"
24

25
#include "expr-impl.h"
26
#include "expr-name.h"
27
#include "dependent.h"
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
28
#include "format.h"
29
#include "func.h"
Jody Goldberg's avatar
Jody Goldberg committed
30
#include "cell.h"
Jody Goldberg's avatar
Jody Goldberg committed
31 32
#include "sheet.h"
#include "str.h"
33
#include "value.h"
34
#include "parse-util.h"
35
#include "ranges.h"
36
#include "number-match.h"
37
#include "workbook.h"
Jeffrey Stedfast's avatar
Jeffrey Stedfast committed
38
#include "gutils.h"
39
#include "parse-util.h"
40
#include "mathfunc.h"
41

42 43
#include <math.h>
#include <string.h>
Jody Goldberg's avatar
Jody Goldberg committed
44
#include <stdlib.h>
45
#include <libgnome/gnome-i18n.h>
46

47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
/*
 * 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

65 66
/***************************************************************************/

Jody Goldberg's avatar
Jody Goldberg committed
67 68 69 70 71 72 73 74 75 76 77 78
#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
79 80
GnmExpr const *
gnm_expr_new_constant (Value *v)
81
{
82
	GnmExprConstant *ans;
83

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

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

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

#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

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

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

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

127
	return (GnmExpr *)ans;
128
}
129

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

#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

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

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

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

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

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

#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
174

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

245
	return (GnmExpr *)ans;
246 247
}

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

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

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

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

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

#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

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

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

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

314
	return (GnmExpr *)ans;
315 316
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	return FALSE;
}

486
/**
487
 * gnm_expr_array_intersection :
488 489 490 491 492 493 494 495 496 497 498 499 500
 * @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 *
501
gnm_expr_array_intersection (Value *a)
502
{
Morten Welinder's avatar
Typo.  
Morten Welinder committed
503
	Value *tmp = value_duplicate (a->v_array.vals[0][0]);
504 505 506 507
	value_release (a);
	return tmp;
}

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

515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533
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
534 535
gnm_expr_extract_ref (CellRef *res, GnmExpr const *expr,
		      EvalPos const *pos, GnmExprEvalFlags flags)
536 537 538 539 540 541 542 543 544
{
	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;

545
		v = function_call_with_list (&ei, expr->func.arg_list, flags);
546 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
		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;
574
		return gnm_expr_extract_ref (res, expr->name.name->t.expr_tree, pos, flags);
575 576 577 578 579 580
	default :
		break;
	}
	return TRUE;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

			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)) {
765 766
			value_release (a);
			value_release (b);
767
			return value_new_error (pos, gnumeric_err_VALUE);
Arturo Espinosa's avatar
Arturo Espinosa committed
768
		}
769

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

915 916 917 918 919 920 921 922 923 924 925 926 927 928
		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);
			res = value_new_string (tmp);
			g_free (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

947 948
	case GNM_EXPR_OP_CELLREF: {
		CellRef const * const ref = &expr->cellref.ref;
Arturo Espinosa's avatar
Arturo Espinosa committed
949
		Cell *cell;