expr.c 54 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
/*
Morten Welinder's avatar
Morten Welinder committed
3
 * expr.c: Expression evaluation in Gnumeric
Miguel de Icaza's avatar
Miguel de Icaza committed
4 5 6 7
 *
 * Author:
 *   Miguel de Icaza (miguel@gnu.org).
 */
8 9
#include <gnumeric-config.h>
#include "gnumeric.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
10
#include "expr.h"
11

12
#include "expr-impl.h"
13
#include "expr-name.h"
14
#include "dependent.h"
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
15
#include "format.h"
16
#include "func.h"
Jody Goldberg's avatar
Jody Goldberg committed
17
#include "cell.h"
Jody Goldberg's avatar
Jody Goldberg committed
18 19
#include "sheet.h"
#include "str.h"
20
#include "value.h"
21
#include "parse-util.h"
22
#include "ranges.h"
23
#include "number-match.h"
24
#include "workbook.h"
Jeffrey Stedfast's avatar
Jeffrey Stedfast committed
25
#include "gutils.h"
26
#include "parse-util.h"
27
#include "mathfunc.h"
28

29 30
#include <math.h>
#include <string.h>
31
#include <libgnome/gnome-i18n.h>
32

33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
/*
 * 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

51 52
/***************************************************************************/

Jody Goldberg's avatar
Jody Goldberg committed
53 54 55 56 57 58 59 60 61 62 63 64
#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
65 66
GnmExpr const *
gnm_expr_new_constant (Value *v)
67
{
68
	GnmExprConstant *ans;
69

70
	ans = CHUNK_ALLOC (GnmExprConstant, expression_pool);
71 72
	if (!ans)
		return NULL;
73
	gnm_expr_constant_init (ans, v);
74

75
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
76 77
}

Jody Goldberg's avatar
Jody Goldberg committed
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
/***************************************************************************/

#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

97 98
GnmExpr const *
gnm_expr_new_funcall (FunctionDefinition *func, GnmExprList *args)
99
{
100
	GnmExprFunction *ans;
Jody Goldberg's avatar
Jody Goldberg committed
101
	g_return_val_if_fail (func, NULL);
102

103
	ans = CHUNK_ALLOC (GnmExprFunction, expression_pool);
104 105
	if (!ans)
		return NULL;
106

107
	ans->ref_count = 1;
108
	ans->oper = GNM_EXPR_OP_FUNCALL;
Jody Goldberg's avatar
Jody Goldberg committed
109
	func_ref (func);
Jody Goldberg's avatar
Jody Goldberg committed
110
	ans->func = func;;
111 112
	ans->arg_list = args;

113
	return (GnmExpr *)ans;
114
}
115

Jody Goldberg's avatar
Jody Goldberg committed
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
/***************************************************************************/

#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

133 134
GnmExpr const *
gnm_expr_new_unary  (GnmExprOp op, GnmExpr const *e)
Morten Welinder's avatar
Morten Welinder committed
135
{
136
	GnmExprUnary *ans;
Morten Welinder's avatar
Morten Welinder committed
137

138
	ans = CHUNK_ALLOC (GnmExprUnary, expression_pool);
139 140 141 142
	if (!ans)
		return NULL;

	ans->ref_count = 1;
143
	ans->oper = op;
144
	ans->value = e;
145

146
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
147 148
}

Jody Goldberg's avatar
Jody Goldberg committed
149 150 151 152 153 154 155 156 157 158 159
/***************************************************************************/

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

161 162
GnmExpr const *
gnm_expr_new_binary (GnmExpr const *l, GnmExprOp op, GnmExpr const *r)
Morten Welinder's avatar
Morten Welinder committed
163
{
164
	GnmExprBinary *ans;
Morten Welinder's avatar
Morten Welinder committed
165

166
	ans = CHUNK_ALLOC (GnmExprBinary, expression_pool);
167 168
	if (!ans)
		return NULL;
169

170
	ans->ref_count = 1;
171
	ans->oper = op;
172 173
	ans->value_a = l;
	ans->value_b = r;
174

175
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
176 177
}

Jody Goldberg's avatar
Jody Goldberg committed
178 179 180 181 182 183 184 185 186 187
/***************************************************************************/

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

188 189
GnmExpr const *
gnm_expr_new_name (GnmNamedExpr *name,
190
		   Sheet *optional_scope, Workbook *optional_wb_scope)
Morten Welinder's avatar
Morten Welinder committed
191
{
192
	GnmExprName *ans;
Morten Welinder's avatar
Morten Welinder committed
193

194
	ans = CHUNK_ALLOC (GnmExprName, expression_pool);
195 196
	if (!ans)
		return NULL;
197

198
	ans->ref_count = 1;
199
	ans->oper = GNM_EXPR_OP_NAME;
200
	ans->name = name;
201
	expr_name_ref (name);
202

203 204 205
	ans->optional_scope = optional_scope;
	ans->optional_wb_scope = optional_wb_scope;

206
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
207
}
208

Jody Goldberg's avatar
Jody Goldberg committed
209 210 211 212 213 214 215 216 217
/***************************************************************************/

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

218 219
GnmExpr const *
gnm_expr_new_cellref (CellRef const *cr)
220
{
221
	GnmExprCellRef *ans;
222

223
	ans = CHUNK_ALLOC (GnmExprCellRef, expression_pool);
224 225
	if (!ans)
		return NULL;
226

227
	ans->ref_count = 1;
228
	ans->oper = GNM_EXPR_OP_CELLREF;
229 230
	ans->ref = *cr;

231
	return (GnmExpr *)ans;
232 233
}

Jody Goldberg's avatar
Jody Goldberg committed
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
/***************************************************************************/

#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.
 **/
253
GnmExpr const *
Jody Goldberg's avatar
Jody Goldberg committed
254
gnm_expr_new_array (int x, int y, int cols, int rows, GnmExpr const *expr)
255
{
256
	GnmExprArray *ans;
257

258
	ans = CHUNK_ALLOC (GnmExprArray, expression_pool);
259 260
	if (ans == NULL)
		return NULL;
261

262
	ans->ref_count = 1;
263
	ans->oper = GNM_EXPR_OP_ARRAY;
264 265 266 267
	ans->x = x;
	ans->y = y;
	ans->rows = rows;
	ans->cols = cols;
268
	ans->corner.value = NULL;
Jody Goldberg's avatar
Jody Goldberg committed
269
	ans->corner.expr = expr;
270
	return (GnmExpr *)ans;
271 272
}

Jody Goldberg's avatar
Jody Goldberg committed
273 274 275 276 277 278 279 280 281 282 283 284 285 286
/***************************************************************************/

#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

287 288
GnmExpr const *
gnm_expr_new_set (GnmExprList *set)
289
{
290
	GnmExprSet *ans;
291

292
	ans = CHUNK_ALLOC (GnmExprSet, expression_pool);
293 294
	if (!ans)
		return NULL;
295

296
	ans->ref_count = 1;
297
	ans->oper = GNM_EXPR_OP_SET;
298
	ans->set = set;
299

300
	return (GnmExpr *)ans;
301 302
}

303
static Cell *
304
expr_array_corner (GnmExpr const *expr,
305
			Sheet const *sheet, CellPos const *pos)
306
{
307 308
	Cell *corner = sheet_cell_get (sheet,
		pos->col - expr->array.x, pos->row - expr->array.y);
309

310
	/* Sanity check incase the corner gets removed for some reason */
311
	g_return_val_if_fail (corner != NULL, NULL);
312
	g_return_val_if_fail (cell_has_expr (corner), NULL);
313
	g_return_val_if_fail (corner->base.expression != (void *)0xdeadbeef, NULL);
314
	g_return_val_if_fail (corner->base.expression->any.oper == GNM_EXPR_OP_ARRAY, NULL);
315 316
	g_return_val_if_fail (corner->base.expression->array.x == 0, NULL);
	g_return_val_if_fail (corner->base.expression->array.y == 0, NULL);
317

318
	return corner;
319 320
}

Jody Goldberg's avatar
Jody Goldberg committed
321 322
/***************************************************************************/

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

333
	((GnmExpr *)expr)->any.ref_count++;
Arturo Espinosa's avatar
Arturo Espinosa committed
334 335 336
}

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

342 343
	switch (expr->any.oper) {
	case GNM_EXPR_OP_CELLREF:
Arturo Espinosa's avatar
Arturo Espinosa committed
344
		break;
345

346 347
	case GNM_EXPR_OP_CONSTANT:
		value_release ((Value *)expr->constant.value);
Arturo Espinosa's avatar
Arturo Espinosa committed
348
		break;
349

350 351
	case GNM_EXPR_OP_FUNCALL:
		gnm_expr_list_unref (expr->func.arg_list);
352
		func_unref (expr->func.func);
Arturo Espinosa's avatar
Arturo Espinosa committed
353 354
		break;

355
	case GNM_EXPR_OP_NAME:
356
		expr_name_unref (expr->name.name);
Michael Meeks's avatar
Michael Meeks committed
357 358
		break;

359 360 361
	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
362 363
		break;

364 365
	case GNM_EXPR_OP_ANY_UNARY:
		do_gnm_expr_unref (expr->unary.value);
Arturo Espinosa's avatar
Arturo Espinosa committed
366
		break;
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
		}
373
		break;
374 375
	case GNM_EXPR_OP_SET:
		gnm_expr_list_unref (expr->set.set);
376 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 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;
}

Jody Goldberg's avatar
Jody Goldberg committed
487
/**
488
 * gnm_expr_implicit_intersection :
Jody Goldberg's avatar
Jody Goldberg committed
489 490
 * @ei: EvalInfo containing valid fd!
 * @v: a VALUE_CELLRANGE
491
 *
492 493 494 495 496
 * Handle the implicit union of a single row or column with the eval position.
 *
 * NOTE : We do not need to know if this is expression is being evaluated as an
 * array or not because we can differentiate based on the required type for the
 * argument.
Jody Goldberg's avatar
Jody Goldberg committed
497 498 499
 *
 * Always release the value passed in.
 *
500
 * Return value:
Jody Goldberg's avatar
Jody Goldberg committed
501 502 503 504
 *     If the intersection succeeded return a duplicate of the value
 *     at the intersection point.  This value needs to be freed.
 **/
Value *
505
gnm_expr_implicit_intersection (EvalPos const *pos, Value *v)
Jody Goldberg's avatar
Jody Goldberg committed
506 507
{
	Value *res = NULL;
508 509 510 511
	Range rng;
	Sheet *start_sheet, *end_sheet;

	/* handle inverted ranges */
Jody Goldberg's avatar
Jody Goldberg committed
512
	value_cellrange_normalize (pos, v, &start_sheet, &end_sheet, &rng);
513 514 515

	if (start_sheet == end_sheet) {
		if (rng.start.row == rng.end.row) {
Jody Goldberg's avatar
Jody Goldberg committed
516
			int const c = pos->eval.col;
Jody Goldberg's avatar
Jody Goldberg committed
517 518 519 520 521 522
			if (rng.start.col <= c && c <= rng.end.col) {
				Value const *tmp = value_area_get_x_y (pos, v,
					c - rng.start.col, 0);
				if (tmp != NULL)
					res = value_duplicate (tmp);
			}
Jody Goldberg's avatar
Jody Goldberg committed
523 524
		}

525
		if (rng.start.col == rng.end.col) {
Jody Goldberg's avatar
Jody Goldberg committed
526
			int const r = pos->eval.row;
Jody Goldberg's avatar
Jody Goldberg committed
527 528 529 530 531 532
			if (rng.start.row <= r && r <= rng.end.row) {
				Value const *tmp = value_area_get_x_y (pos, v,
					0, r - rng.start.row);
				if (tmp != NULL)
					res = value_duplicate (tmp);
			}
Jody Goldberg's avatar
Jody Goldberg committed
533 534 535 536 537 538
		}
	}
	value_release (v);
	return res;
}

539
/**
540
 * gnm_expr_array_intersection :
541 542 543 544 545 546 547 548 549 550 551 552 553
 * @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 *
554
gnm_expr_array_intersection (Value *a)
555
{
Morten Welinder's avatar
Typo.  
Morten Welinder committed
556
	Value *tmp = value_duplicate (a->v_array.vals[0][0]);
557 558 559 560
	value_release (a);
	return tmp;
}

Jody Goldberg's avatar
Jody Goldberg committed
561 562
static Value *
cb_range_eval (Sheet *sheet, int col, int row, Cell *cell, void *ignore)
563
{
Jody Goldberg's avatar
Jody Goldberg committed
564 565
	cell_eval (cell);
	return NULL;
566 567
}

568
static Value *
569 570
expr_eval_real (GnmExpr const *expr, EvalPos const *pos,
		GnmExprEvalFlags flags)
Arturo Espinosa's avatar
Arturo Espinosa committed
571
{
572
	Value *res = NULL, *a = NULL, *b = NULL;
573

574
	g_return_val_if_fail (expr != NULL, NULL);
575
	g_return_val_if_fail (pos != NULL, NULL);
576

577
	switch (expr->any.oper){
578 579 580 581 582 583
	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: {
584
		ValueCompare comp;
585

586
		a = expr_eval_real (expr->binary.value_a, pos, flags);
Jody Goldberg's avatar
Jody Goldberg committed
587 588
		if (a != NULL) {
			if (a->type == VALUE_CELLRANGE) {
589
				a = gnm_expr_implicit_intersection (pos, a);
Jody Goldberg's avatar
Jody Goldberg committed
590
				if (a == NULL)
591
					return value_new_error (pos, gnumeric_err_VALUE);
592
			} else if (a->type == VALUE_ARRAY) {
593
				a = gnm_expr_array_intersection (a);
594 595
				if (a == NULL)
					return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
596 597 598
			} else if (a->type == VALUE_ERROR)
				return a;
		}
Morten Welinder's avatar
Morten Welinder committed
599

600
		b = expr_eval_real (expr->binary.value_b, pos, flags);
Jody Goldberg's avatar
Jody Goldberg committed
601 602 603
		if (b != NULL) {
			Value *res = NULL;
			if (b->type == VALUE_CELLRANGE) {
604
				b = gnm_expr_implicit_intersection (pos, b);
Jody Goldberg's avatar
Jody Goldberg committed
605
				if (b == NULL)
606
					res = value_new_error (pos, gnumeric_err_VALUE);
607
			} else if (b->type == VALUE_ARRAY) {
608
				b = gnm_expr_array_intersection (b);
609 610
				if (b == NULL)
					return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
611 612 613 614 615 616 617 618
			} 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
619
		}
620

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

623 624 625 626
		if (a != NULL)
			value_release (a);
		if (b != NULL)
			value_release (b);
627

Michael Meeks's avatar
Michael Meeks committed
628
		if (comp == TYPE_MISMATCH) {
629 630 631 632
			/* TODO TODO TODO : Make error more informative
			 *    regarding what is comparing to what
			 */
			/* For equality comparisons even errors are ok */
633
			if (expr->any.oper == GNM_EXPR_OP_EQUAL)
634
				return value_new_bool (FALSE);
635
			if (expr->any.oper == GNM_EXPR_OP_NOT_EQUAL)
636 637
				return value_new_bool (TRUE);

638
			return value_new_error (pos, gnumeric_err_VALUE);
639
		}
640

641
		switch (expr->any.oper) {
642
		case GNM_EXPR_OP_EQUAL:
643
			res = value_new_bool (comp == IS_EQUAL);
Arturo Espinosa's avatar
Arturo Espinosa committed
644 645
			break;

646
		case GNM_EXPR_OP_GT:
647
			res = value_new_bool (comp == IS_GREATER);
Arturo Espinosa's avatar
Arturo Espinosa committed
648 649
			break;

650
		case GNM_EXPR_OP_LT:
651
			res = value_new_bool (comp == IS_LESS);
Arturo Espinosa's avatar
Arturo Espinosa committed
652 653
			break;

654
		case GNM_EXPR_OP_NOT_EQUAL:
655
			res = value_new_bool (comp != IS_EQUAL);
Arturo Espinosa's avatar
Arturo Espinosa committed
656 657
			break;

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

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

Arturo Espinosa's avatar
Arturo Espinosa committed
666
		default:
667
			g_assert_not_reached ();
668
			res = value_new_error (pos,
669
						_("Internal type error"));
Arturo Espinosa's avatar
Arturo Espinosa committed
670
		}
Morten Welinder's avatar
Morten Welinder committed
671
		return res;
Arturo Espinosa's avatar
Arturo Espinosa committed
672
	}
673

674 675 676 677 678
	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:
679 680 681 682 683 684 685 686 687
		/*
		 * 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
		 */

688
	        /* Guarantees a != NULL */
689 690
		a = gnm_expr_eval (expr->binary.value_a, pos,
			       flags & (~GNM_EXPR_EVAL_PERMIT_EMPTY));
Jody Goldberg's avatar
Jody Goldberg committed
691 692 693

		/* Handle implicit intersection */
		if (a->type == VALUE_CELLRANGE) {
694
			a = gnm_expr_implicit_intersection (pos, a);
Jody Goldberg's avatar
Jody Goldberg committed
695
			if (a == NULL)
696
				return value_new_error (pos, gnumeric_err_VALUE);
697
		} else if (a->type == VALUE_ARRAY) {
698
			a = gnm_expr_array_intersection (a);
699 700
			if (a == NULL)
				return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
701 702
		}

703 704
		/* 1) Error from A */
		if (a->type == VALUE_ERROR)
705
			return value_error_set_pos (&a->v_err, pos);
706

707
		/* 2) #!VALUE error if A is not a number */
708
		if (a->type == VALUE_STRING) {
709
			Value *tmp = format_match_number (a->v_str.val->str, NULL);
710 711 712 713 714 715

			value_release (a);
			if (tmp == NULL)
				return value_new_error (pos, gnumeric_err_VALUE);
			a = tmp;
		} else if (!VALUE_IS_NUMBER (a)) {
716
			value_release (a);
717
			return value_new_error (pos, gnumeric_err_VALUE);
718 719
		}

720
	        /* Guarantees that b != NULL */
721 722
		b = gnm_expr_eval (expr->binary.value_b, pos,
			       flags & (~GNM_EXPR_EVAL_PERMIT_EMPTY));
Arturo Espinosa's avatar
Arturo Espinosa committed
723

Jody Goldberg's avatar
Jody Goldberg committed
724 725
		/* Handle implicit intersection */
		if (b->type == VALUE_CELLRANGE) {
726
			b = gnm_expr_implicit_intersection (pos, a);
Jody Goldberg's avatar
Jody Goldberg committed
727
			if (b == NULL)
728
				return value_new_error (pos, gnumeric_err_VALUE);
729
		} else if (b->type == VALUE_ARRAY) {
730
			b = gnm_expr_array_intersection (b);
731 732
			if (b == NULL)
				return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
733 734
		}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

862 863
		if (a->type == VALUE_ERROR)
			return a;
Jody Goldberg's avatar
Jody Goldberg committed
864

865
		if (expr->any.oper == GNM_EXPR_OP_UNARY_PLUS)
Jody Goldberg's avatar
Jody Goldberg committed
866 867
			return a;

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

891
	case GNM_EXPR_OP_CAT:
892
		a = expr_eval_real (expr->binary.value_a, pos, flags);
893
		if (a != NULL && a->type == VALUE_ERROR)
894
			return a;
895
		b = expr_eval_real (expr->binary.value_b, pos, flags);
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 914 915
		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);