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

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>
Jody Goldberg's avatar
Jody Goldberg committed
31
#include <stdlib.h>
32
#include <libgnome/gnome-i18n.h>
33

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

52 53
/***************************************************************************/

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

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

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

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

#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

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

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

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

114
	return (GnmExpr *)ans;
115
}
116

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

#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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

232
	return (GnmExpr *)ans;
233 234
}

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

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

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

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

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

#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

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

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

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

301
	return (GnmExpr *)ans;
302 303
}

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

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

319
	return corner;
320 321
}

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

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

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

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

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

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

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

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

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

365 366
	case GNM_EXPR_OP_ANY_UNARY:
		do_gnm_expr_unref (expr->unary.value);
Arturo Espinosa's avatar
Arturo Espinosa committed
367
		break;
368
	case GNM_EXPR_OP_ARRAY:
369 370 371
		if (expr->array.x == 0 && expr->array.y == 0) {
			if (expr->array.corner.value)
				value_release (expr->array.corner.value);
372
			do_gnm_expr_unref (expr->array.corner.expr);
373
		}
374
		break;
375 376
	case GNM_EXPR_OP_SET:
		gnm_expr_list_unref (expr->set.set);
377 378
		break;

379
	default:
380
		g_warning ("do_gnm_expr_unref error.");
381
		break;
Arturo Espinosa's avatar
Arturo Espinosa committed
382
	}
383

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	return FALSE;
}

Jody Goldberg's avatar
Jody Goldberg committed
488
/**
489
 * gnm_expr_implicit_intersection :
Jody Goldberg's avatar
Jody Goldberg committed
490 491
 * @ei: EvalInfo containing valid fd!
 * @v: a VALUE_CELLRANGE
492
 *
493 494 495 496 497
 * 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
498 499 500
 *
 * Always release the value passed in.
 *
501
 * Return value:
Jody Goldberg's avatar
Jody Goldberg committed
502 503 504 505
 *     If the intersection succeeded return a duplicate of the value
 *     at the intersection point.  This value needs to be freed.
 **/
Value *
506
gnm_expr_implicit_intersection (EvalPos const *pos, Value *v)
Jody Goldberg's avatar
Jody Goldberg committed
507 508
{
	Value *res = NULL;
509 510 511 512
	Range rng;
	Sheet *start_sheet, *end_sheet;

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

	if (start_sheet == end_sheet) {
		if (rng.start.row == rng.end.row) {
Jody Goldberg's avatar
Jody Goldberg committed
517
			int const c = pos->eval.col;
Jody Goldberg's avatar
Jody Goldberg committed
518 519 520 521 522 523
			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
524 525
		}

526
		if (rng.start.col == rng.end.col) {
Jody Goldberg's avatar
Jody Goldberg committed
527
			int const r = pos->eval.row;
Jody Goldberg's avatar
Jody Goldberg committed
528 529 530 531 532 533
			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
534 535 536 537 538 539
		}
	}
	value_release (v);
	return res;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Jody Goldberg's avatar
Jody Goldberg committed
725 726
		/* Handle implicit intersection */
		if (b->type == VALUE_CELLRANGE) {
727
			b = gnm_expr_implicit_intersection (pos, a);
Jody Goldberg's avatar
Jody Goldberg committed
728
			if (b == NULL)
729
				return value_new_error (pos, gnumeric_err_VALUE);
730
		} else if (b->type == VALUE_ARRAY) {
731
			b = gnm_expr_array_intersection (b);
732 733
			if (b == NULL)
				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 850
		a = gnm_expr_eval (expr->unary.value, pos,
			flags & (~GNM_EXPR_EVAL_PERMIT_EMPTY));
Jody Goldberg's avatar
Jody Goldberg committed
851 852 853

		/* Handle implicit intersection */
		if (a->type == VALUE_CELLRANGE) {
854
			a = gnm_expr_implicit_intersection (pos, a);
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
		} else if (a->type == VALUE_ARRAY) {
858
			a = gnm_expr_array_intersection (a);
859 860
			if (a == NULL)
				return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
861 862
		}

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

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

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

892
	case GNM_EXPR_OP_CAT:
893
		a = expr_eval_real (expr->binary.value_a, pos, flags);
894
		if (a != NULL && a->type == VALUE_ERROR)
895
			return a;
896
		b = expr_eval_real (expr->binary.value_b, pos, flags);
897 898 899
		if (b != NULL && b->type == VALUE_ERROR) {
			if (a != NULL)
				value_release (a);
900
			return b;
901 902
		}

903 904 905 906 907 908 909 910 911 912 913 914 915 916
		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)