expr.c 52.3 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
/***************************************************************************/

53 54
GnmExpr const *
gnm_expr_new_constant (Value *v)
55
{
56
	GnmExprConstant *ans;
57

58
	ans = CHUNK_ALLOC (GnmExprConstant, expression_pool);
59 60
	if (!ans)
		return NULL;
61
	gnm_expr_constant_init (ans, v);
62

63
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
64 65
}

66 67
GnmExpr const *
gnm_expr_new_error (char const *txt)
68
{
Jody Goldberg's avatar
Jody Goldberg committed
69
	FunctionDefinition *func;
70
	GnmExprList *args = NULL;
71

Jody Goldberg's avatar
Jody Goldberg committed
72 73
	if (strcmp (txt, gnumeric_err_NA) != 0) {
		func = func_lookup_by_name ("ERROR", NULL);
74 75
		args = gnm_expr_list_prepend (NULL,
			gnm_expr_new_constant (value_new_string (txt)));
Jody Goldberg's avatar
Jody Goldberg committed
76 77
	} else
		func = func_lookup_by_name ("NA", NULL);
78

Jody Goldberg's avatar
Jody Goldberg committed
79
	func_ref (func);
80
	return gnm_expr_new_funcall (func, args);
81 82
}

83 84
GnmExpr const *
gnm_expr_new_funcall (FunctionDefinition *func, GnmExprList *args)
85
{
86
	GnmExprFunction *ans;
Jody Goldberg's avatar
Jody Goldberg committed
87
	g_return_val_if_fail (func, NULL);
88

89
	ans = CHUNK_ALLOC (GnmExprFunction, expression_pool);
90 91
	if (!ans)
		return NULL;
92

93
	ans->ref_count = 1;
94
	ans->oper = GNM_EXPR_OP_FUNCALL;
Jody Goldberg's avatar
Jody Goldberg committed
95
	func_ref (func);
Jody Goldberg's avatar
Jody Goldberg committed
96
	ans->func = func;;
97 98
	ans->arg_list = args;

99
	return (GnmExpr *)ans;
100
}
101

102 103
GnmExpr const *
gnm_expr_new_unary  (GnmExprOp op, GnmExpr const *e)
Morten Welinder's avatar
Morten Welinder committed
104
{
105
	GnmExprUnary *ans;
Morten Welinder's avatar
Morten Welinder committed
106

107
	ans = CHUNK_ALLOC (GnmExprUnary, expression_pool);
108 109 110 111
	if (!ans)
		return NULL;

	ans->ref_count = 1;
112
	ans->oper = op;
113
	ans->value = e;
114

115
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
116 117 118
}


119 120
GnmExpr const *
gnm_expr_new_binary (GnmExpr const *l, GnmExprOp op, GnmExpr const *r)
Morten Welinder's avatar
Morten Welinder committed
121
{
122
	GnmExprBinary *ans;
Morten Welinder's avatar
Morten Welinder committed
123

124
	ans = CHUNK_ALLOC (GnmExprBinary, expression_pool);
125 126
	if (!ans)
		return NULL;
127

128
	ans->ref_count = 1;
129
	ans->oper = op;
130 131
	ans->value_a = l;
	ans->value_b = r;
132

133
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
134 135
}

136 137
GnmExpr const *
gnm_expr_new_name (GnmNamedExpr *name,
138
		    Sheet *optional_scope, Workbook *optional_wb_scope)
Morten Welinder's avatar
Morten Welinder committed
139
{
140
	GnmExprName *ans;
Morten Welinder's avatar
Morten Welinder committed
141

142
	ans = CHUNK_ALLOC (GnmExprName, expression_pool);
143 144
	if (!ans)
		return NULL;
145

146
	ans->ref_count = 1;
147
	ans->oper = GNM_EXPR_OP_NAME;
148
	ans->name = name;
149
	expr_name_ref (name);
150

151 152 153
	ans->optional_scope = optional_scope;
	ans->optional_wb_scope = optional_wb_scope;

154
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
155
}
156

157 158
GnmExpr const *
gnm_expr_new_cellref (CellRef const *cr)
159
{
160
	GnmExprCellRef *ans;
161

162
	ans = CHUNK_ALLOC (GnmExprCellRef, expression_pool);
163 164
	if (!ans)
		return NULL;
165

166
	ans->ref_count = 1;
167
	ans->oper = GNM_EXPR_OP_CELLREF;
168 169
	ans->ref = *cr;

170
	return (GnmExpr *)ans;
171 172
}

173 174
GnmExpr const *
gnm_expr_new_array (int x, int y, int cols, int rows)
175
{
176
	GnmExprArray *ans;
177

178
	ans = CHUNK_ALLOC (GnmExprArray, expression_pool);
179 180
	if (ans == NULL)
		return NULL;
181

182
	ans->ref_count = 1;
183
	ans->oper = GNM_EXPR_OP_ARRAY;
184 185 186 187
	ans->x = x;
	ans->y = y;
	ans->rows = rows;
	ans->cols = cols;
188 189
	ans->corner.value = NULL;
	ans->corner.expr = NULL;
190
	return (GnmExpr *)ans;
191 192
}

193 194
GnmExpr const *
gnm_expr_new_set (GnmExprList *set)
195
{
196
	GnmExprSet *ans;
197

198
	ans = CHUNK_ALLOC (GnmExprSet, expression_pool);
199 200
	if (!ans)
		return NULL;
201

202
	ans->ref_count = 1;
203
	ans->oper = GNM_EXPR_OP_SET;
204
	ans->set = set;
205

206
	return (GnmExpr *)ans;
207 208
}

209
static Cell *
210
expr_array_corner (GnmExpr const *expr,
211
			Sheet const *sheet, CellPos const *pos)
212
{
213 214
	Cell *corner = sheet_cell_get (sheet,
		pos->col - expr->array.x, pos->row - expr->array.y);
215

216
	/* Sanity check incase the corner gets removed for some reason */
217
	g_return_val_if_fail (corner != NULL, NULL);
218
	g_return_val_if_fail (cell_has_expr (corner), NULL);
219
	g_return_val_if_fail (corner->base.expression != (void *)0xdeadbeef, NULL);
220
	g_return_val_if_fail (corner->base.expression->any.oper == GNM_EXPR_OP_ARRAY, NULL);
221 222
	g_return_val_if_fail (corner->base.expression->array.x == 0, NULL);
	g_return_val_if_fail (corner->base.expression->array.y == 0, NULL);
223

224
	return corner;
225 226
}

227 228 229
/**
 * gnm_expr_ref:
 * Increments the ref_count for an expression node.
Arturo Espinosa's avatar
Arturo Espinosa committed
230
 */
231
void
232
gnm_expr_ref (GnmExpr const *expr)
233
{
234 235
	g_return_if_fail (expr != NULL);
	g_return_if_fail (expr->any.ref_count > 0);
236

237
	((GnmExpr *)expr)->any.ref_count++;
Arturo Espinosa's avatar
Arturo Espinosa committed
238 239 240
}

static void
241
do_gnm_expr_unref (GnmExpr const *expr)
Arturo Espinosa's avatar
Arturo Espinosa committed
242
{
243
	if (--((GnmExpr *)expr)->any.ref_count > 0)
Morten Welinder's avatar
Morten Welinder committed
244 245
		return;

246 247
	switch (expr->any.oper) {
	case GNM_EXPR_OP_CELLREF:
Arturo Espinosa's avatar
Arturo Espinosa committed
248
		break;
249

250 251
	case GNM_EXPR_OP_CONSTANT:
		value_release ((Value *)expr->constant.value);
Arturo Espinosa's avatar
Arturo Espinosa committed
252
		break;
253

254 255
	case GNM_EXPR_OP_FUNCALL:
		gnm_expr_list_unref (expr->func.arg_list);
256
		func_unref (expr->func.func);
Arturo Espinosa's avatar
Arturo Espinosa committed
257 258
		break;

259
	case GNM_EXPR_OP_NAME:
260
		expr_name_unref (expr->name.name);
Michael Meeks's avatar
Michael Meeks committed
261 262
		break;

263 264 265
	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
266 267
		break;

268 269
	case GNM_EXPR_OP_ANY_UNARY:
		do_gnm_expr_unref (expr->unary.value);
Arturo Espinosa's avatar
Arturo Espinosa committed
270
		break;
271
	case GNM_EXPR_OP_ARRAY:
272 273 274
		if (expr->array.x == 0 && expr->array.y == 0) {
			if (expr->array.corner.value)
				value_release (expr->array.corner.value);
275
			do_gnm_expr_unref (expr->array.corner.expr);
276
		}
277
		break;
278 279
	case GNM_EXPR_OP_SET:
		gnm_expr_list_unref (expr->set.set);
280 281
		break;

282
	default:
283
		g_warning ("do_gnm_expr_unref error.");
284
		break;
Arturo Espinosa's avatar
Arturo Espinosa committed
285
	}
286

287
	CHUNK_FREE (expression_pool, (gpointer)expr);
288 289
}

Morten Welinder's avatar
Morten Welinder committed
290
/*
291 292
 * gnm_expr_unref:
 * Decrements the ref_count for part of a expression.  (All trees are expected
Morten Welinder's avatar
Morten Welinder committed
293 294 295
 * 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.)
 */
296
void
297
gnm_expr_unref (GnmExpr const *expr)
298
{
299 300
	g_return_if_fail (expr != NULL);
	g_return_if_fail (expr->any.ref_count > 0);
301

302
	if (expr->any.ref_count == 1)
303
		do_gnm_expr_unref (expr);
304
	else
305
		((GnmExpr *)expr)->any.ref_count--;
306 307
}

Jody Goldberg's avatar
Jody Goldberg committed
308
/**
309
 * gnm_expr_is_shared : Returns TRUE if the reference count
Jody Goldberg's avatar
Jody Goldberg committed
310 311 312
 *   for the supplied expression is > 1
 */
gboolean
313
gnm_expr_is_shared (GnmExpr const *expr)
Jody Goldberg's avatar
Jody Goldberg committed
314
{
315
	g_return_val_if_fail (expr != NULL, FALSE);
Jody Goldberg's avatar
Jody Goldberg committed
316

317
	return (expr->any.ref_count > 1);
Jody Goldberg's avatar
Jody Goldberg committed
318 319
}

Jody Goldberg's avatar
Jody Goldberg committed
320
/**
321
 * gnm_expr_equal : Returns TRUE if the supplied expressions are exactly the
Jody Goldberg's avatar
Jody Goldberg committed
322 323 324 325 326
 *   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
327
gnm_expr_equal (GnmExpr const *a, GnmExpr const *b)
Jody Goldberg's avatar
Jody Goldberg committed
328 329 330 331 332 333 334 335 336 337 338
{
	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) {
339 340 341
	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
342

343 344
	case GNM_EXPR_OP_ANY_UNARY:
		return gnm_expr_equal (a->unary.value, b->unary.value);
Jody Goldberg's avatar
Jody Goldberg committed
345

346
	case GNM_EXPR_OP_FUNCALL:
347
		return (a->func.func == b->func.func) &&
348
			gnm_expr_list_equal (a->func.arg_list, b->func.arg_list);
Jody Goldberg's avatar
Jody Goldberg committed
349

350
	case GNM_EXPR_OP_NAME:
Jody Goldberg's avatar
Jody Goldberg committed
351 352
		return a->name.name == b->name.name;

353 354
	case GNM_EXPR_OP_CELLREF:
		return cellref_equal (&a->cellref.ref, &b->cellref.ref);
Jody Goldberg's avatar
Jody Goldberg committed
355

356
	case GNM_EXPR_OP_CONSTANT: {
Jody Goldberg's avatar
Jody Goldberg committed
357 358 359 360 361 362 363 364 365 366 367 368 369
		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;
	}

370 371 372
	case GNM_EXPR_OP_ARRAY: {
		GnmExprArray const *aa = &a->array;
		GnmExprArray const *ab = &b->array;
Jody Goldberg's avatar
Jody Goldberg committed
373 374 375 376 377

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

381 382
	case GNM_EXPR_OP_SET:
		return gnm_expr_list_equal (a->set.set, b->set.set);
383

Jody Goldberg's avatar
Jody Goldberg committed
384 385 386 387 388 389 390
	default :
		g_assert_not_reached ();
	}

	return FALSE;
}

Jody Goldberg's avatar
Jody Goldberg committed
391
/**
392
 * gnm_expr_implicit_intersection :
Jody Goldberg's avatar
Jody Goldberg committed
393 394
 * @ei: EvalInfo containing valid fd!
 * @v: a VALUE_CELLRANGE
395
 *
396 397 398 399 400
 * 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
401 402 403
 *
 * Always release the value passed in.
 *
404
 * Return value:
Jody Goldberg's avatar
Jody Goldberg committed
405 406 407 408
 *     If the intersection succeeded return a duplicate of the value
 *     at the intersection point.  This value needs to be freed.
 **/
Value *
409
gnm_expr_implicit_intersection (EvalPos const *pos, Value *v)
Jody Goldberg's avatar
Jody Goldberg committed
410 411
{
	Value *res = NULL;
412 413 414 415
	Range rng;
	Sheet *start_sheet, *end_sheet;

	/* handle inverted ranges */
Jody Goldberg's avatar
Jody Goldberg committed
416
	value_cellrange_normalize (pos, v, &start_sheet, &end_sheet, &rng);
417 418 419

	if (start_sheet == end_sheet) {
		if (rng.start.row == rng.end.row) {
Jody Goldberg's avatar
Jody Goldberg committed
420
			int const c = pos->eval.col;
Jody Goldberg's avatar
Jody Goldberg committed
421 422 423 424 425 426
			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
427 428
		}

429
		if (rng.start.col == rng.end.col) {
Jody Goldberg's avatar
Jody Goldberg committed
430
			int const r = pos->eval.row;
Jody Goldberg's avatar
Jody Goldberg committed
431 432 433 434 435 436
			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
437 438 439 440 441 442
		}
	}
	value_release (v);
	return res;
}

443
/**
444
 * gnm_expr_array_intersection :
445 446 447 448 449 450 451 452 453 454 455 456 457
 * @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 *
458
gnm_expr_array_intersection (Value *a)
459 460 461 462 463 464
{
	Value *tmp = value_duplicate (a->v_array.vals [0][0]);
	value_release (a);
	return tmp;
}

Jody Goldberg's avatar
Jody Goldberg committed
465 466
static Value *
cb_range_eval (Sheet *sheet, int col, int row, Cell *cell, void *ignore)
467
{
Jody Goldberg's avatar
Jody Goldberg committed
468 469
	cell_eval (cell);
	return NULL;
470 471
}

472
static Value *
473 474
expr_eval_real (GnmExpr const *expr, EvalPos const *pos,
		GnmExprEvalFlags flags)
Arturo Espinosa's avatar
Arturo Espinosa committed
475
{
476
	Value *res = NULL, *a = NULL, *b = NULL;
477

478
	g_return_val_if_fail (expr != NULL, NULL);
479
	g_return_val_if_fail (pos != NULL, NULL);
480

481
	switch (expr->any.oper){
482 483 484 485 486 487
	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: {
488
		ValueCompare comp;
489

490
		a = expr_eval_real (expr->binary.value_a, pos, flags);
Jody Goldberg's avatar
Jody Goldberg committed
491 492
		if (a != NULL) {
			if (a->type == VALUE_CELLRANGE) {
493
				a = gnm_expr_implicit_intersection (pos, a);
Jody Goldberg's avatar
Jody Goldberg committed
494
				if (a == NULL)
495
					return value_new_error (pos, gnumeric_err_VALUE);
496
			} else if (a->type == VALUE_ARRAY) {
497
				a = gnm_expr_array_intersection (a);
498 499
				if (a == NULL)
					return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
500 501 502
			} else if (a->type == VALUE_ERROR)
				return a;
		}
Morten Welinder's avatar
Morten Welinder committed
503

504
		b = expr_eval_real (expr->binary.value_b, pos, flags);
Jody Goldberg's avatar
Jody Goldberg committed
505 506 507
		if (b != NULL) {
			Value *res = NULL;
			if (b->type == VALUE_CELLRANGE) {
508
				b = gnm_expr_implicit_intersection (pos, b);
Jody Goldberg's avatar
Jody Goldberg committed
509
				if (b == NULL)
510
					res = value_new_error (pos, gnumeric_err_VALUE);
511
			} else if (b->type == VALUE_ARRAY) {
512
				b = gnm_expr_array_intersection (b);
513 514
				if (b == NULL)
					return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
515 516 517 518 519 520 521 522
			} 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
523
		}
524

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

527 528 529 530
		if (a != NULL)
			value_release (a);
		if (b != NULL)
			value_release (b);
531

Michael Meeks's avatar
Michael Meeks committed
532
		if (comp == TYPE_MISMATCH) {
533 534 535 536
			/* TODO TODO TODO : Make error more informative
			 *    regarding what is comparing to what
			 */
			/* For equality comparisons even errors are ok */
537
			if (expr->any.oper == GNM_EXPR_OP_EQUAL)
538
				return value_new_bool (FALSE);
539
			if (expr->any.oper == GNM_EXPR_OP_NOT_EQUAL)
540 541
				return value_new_bool (TRUE);

542
			return value_new_error (pos, gnumeric_err_VALUE);
543
		}
544

545
		switch (expr->any.oper) {
546
		case GNM_EXPR_OP_EQUAL:
547
			res = value_new_bool (comp == IS_EQUAL);
Arturo Espinosa's avatar
Arturo Espinosa committed
548 549
			break;

550
		case GNM_EXPR_OP_GT:
551
			res = value_new_bool (comp == IS_GREATER);
Arturo Espinosa's avatar
Arturo Espinosa committed
552 553
			break;

554
		case GNM_EXPR_OP_LT:
555
			res = value_new_bool (comp == IS_LESS);
Arturo Espinosa's avatar
Arturo Espinosa committed
556 557
			break;

558
		case GNM_EXPR_OP_NOT_EQUAL:
559
			res = value_new_bool (comp != IS_EQUAL);
Arturo Espinosa's avatar
Arturo Espinosa committed
560 561
			break;

562
		case GNM_EXPR_OP_LTE:
563
			res = value_new_bool (comp != IS_GREATER);
Arturo Espinosa's avatar
Arturo Espinosa committed
564 565
			break;

566
		case GNM_EXPR_OP_GTE:
567
			res = value_new_bool (comp != IS_LESS);
Arturo Espinosa's avatar
Arturo Espinosa committed
568
			break;
569

Arturo Espinosa's avatar
Arturo Espinosa committed
570
		default:
571
			g_assert_not_reached ();
572
			res = value_new_error (pos,
573
						_("Internal type error"));
Arturo Espinosa's avatar
Arturo Espinosa committed
574
		}
Morten Welinder's avatar
Morten Welinder committed
575
		return res;
Arturo Espinosa's avatar
Arturo Espinosa committed
576
	}
577

578 579 580 581 582
	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:
583 584 585 586 587 588 589 590 591
		/*
		 * 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
		 */

592
	        /* Guarantees a != NULL */
593 594
		a = gnm_expr_eval (expr->binary.value_a, pos,
			       flags & (~GNM_EXPR_EVAL_PERMIT_EMPTY));
Jody Goldberg's avatar
Jody Goldberg committed
595 596 597

		/* Handle implicit intersection */
		if (a->type == VALUE_CELLRANGE) {
598
			a = gnm_expr_implicit_intersection (pos, a);
Jody Goldberg's avatar
Jody Goldberg committed
599
			if (a == NULL)
600
				return value_new_error (pos, gnumeric_err_VALUE);
601
		} else if (a->type == VALUE_ARRAY) {
602
			a = gnm_expr_array_intersection (a);
603 604
			if (a == NULL)
				return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
605 606
		}

607 608
		/* 1) Error from A */
		if (a->type == VALUE_ERROR)
609
			return value_error_set_pos (&a->v_err, pos);
610

611
		/* 2) #!VALUE error if A is not a number */
612
		if (a->type == VALUE_STRING) {
613
			Value *tmp = format_match_number (a->v_str.val->str, NULL);
614 615 616 617 618 619

			value_release (a);
			if (tmp == NULL)
				return value_new_error (pos, gnumeric_err_VALUE);
			a = tmp;
		} else if (!VALUE_IS_NUMBER (a)) {
620
			value_release (a);
621
			return value_new_error (pos, gnumeric_err_VALUE);
622 623
		}

624
	        /* Guarantees that b != NULL */
625 626
		b = gnm_expr_eval (expr->binary.value_b, pos,
			       flags & (~GNM_EXPR_EVAL_PERMIT_EMPTY));
Arturo Espinosa's avatar
Arturo Espinosa committed
627

Jody Goldberg's avatar
Jody Goldberg committed
628 629
		/* Handle implicit intersection */
		if (b->type == VALUE_CELLRANGE) {
630
			b = gnm_expr_implicit_intersection (pos, a);
Jody Goldberg's avatar
Jody Goldberg committed
631
			if (b == NULL)
632
				return value_new_error (pos, gnumeric_err_VALUE);
633
		} else if (b->type == VALUE_ARRAY) {
634
			b = gnm_expr_array_intersection (b);
635 636
			if (b == NULL)
				return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
637 638
		}

639 640
		/* 3) Error from B */
		if (b->type == VALUE_ERROR) {
641
			value_release (a);
642
			return value_error_set_pos (&b->v_err, pos);
Arturo Espinosa's avatar
Arturo Espinosa committed
643
		}
644

645
		/* 4) #!VALUE error if B is not a number */
646
		if (b->type == VALUE_STRING) {
647
			Value *tmp = format_match_number (b->v_str.val->str, NULL);
648 649 650 651 652 653 654 655

			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)) {
656 657
			value_release (a);
			value_release (b);
658
			return value_new_error (pos, gnumeric_err_VALUE);
Arturo Espinosa's avatar
Arturo Espinosa committed
659
		}
660

661
		if (a->type != VALUE_FLOAT && b->type != VALUE_FLOAT){
Morten Welinder's avatar
Morten Welinder committed
662
			int ia = value_get_as_int (a);
663
			int ib = value_get_as_int (b);
664
			gnum_float dres;
665 666
			int ires;

Morten Welinder's avatar
Morten Welinder committed
667 668
			value_release (a);
			value_release (b);
669

670 671
			/* FIXME: we could use simple (cheap) heuristics to
			   catch most cases where overflow will not happen.  */
672
			switch (expr->any.oper){
673
			case GNM_EXPR_OP_ADD:
674
				dres = (gnum_float)ia + (gnum_float)ib;
Morten Welinder's avatar
Morten Welinder committed
675
				break;
676

677
			case GNM_EXPR_OP_SUB:
678
				dres = (gnum_float)ia - (gnum_float)ib;
Morten Welinder's avatar
Morten Welinder committed
679
				break;
680

681
			case GNM_EXPR_OP_MULT:
682
				dres = (gnum_float)ia * (gnum_float)ib;
Morten Welinder's avatar
Morten Welinder committed
683
				break;
Arturo Espinosa's avatar
Arturo Espinosa committed
684

685
			case GNM_EXPR_OP_DIV:
686
				if (ib == 0)
687
					return value_new_error (pos, gnumeric_err_DIV0);
688
				dres = (gnum_float)ia / (gnum_float)ib;
Morten Welinder's avatar
Morten Welinder committed
689
				break;
690

691
			case GNM_EXPR_OP_EXP:
692
				if (ia == 0 && ib <= 0)
693
					return value_new_error (pos, gnumeric_err_NUM);
694
				dres = powgnum ((gnum_float)ia, (gnum_float)ib);
695 696
				if (!finitegnum (dres))
					return value_new_error (pos, gnumeric_err_NUM);
Morten Welinder's avatar
Morten Welinder committed
697
				break;
698

Arturo Espinosa's avatar
Arturo Espinosa committed
699
			default:
700
				abort ();
Arturo Espinosa's avatar
Arturo Espinosa committed
701
			}
Morten Welinder's avatar
Morten Welinder committed
702 703 704 705 706 707

			ires = (int)dres;
			if (dres == ires)
				return value_new_int (ires);
			else
				return value_new_float (dres);
Arturo Espinosa's avatar
Arturo Espinosa committed
708
		} else {
709 710
			gnum_float const va = value_get_as_float (a);
			gnum_float const vb = value_get_as_float (b);
711 712
			value_release (a);
			value_release (b);
713

714
			switch (expr->any.oper){
715
			case GNM_EXPR_OP_ADD:
Arturo Espinosa's avatar
Arturo Espinosa committed
716
				return value_new_float (va + vb);
717

718
			case GNM_EXPR_OP_SUB:
Arturo Espinosa's avatar
Arturo Espinosa committed
719
				return value_new_float (va - vb);
720

721
			case GNM_EXPR_OP_MULT:
Arturo Espinosa's avatar
Arturo Espinosa committed
722
				return value_new_float (va * vb);
723

724
			case GNM_EXPR_OP_DIV:
725
				return (vb == 0.0)
726
				    ? value_new_error (pos,
727
						       gnumeric_err_DIV0)
Arturo Espinosa's avatar
Arturo Espinosa committed
728
				    : value_new_float (va / vb);
729

730 731
			case GNM_EXPR_OP_EXP: {
				gnum_float res;
732 733
				if ((va == 0 && vb <= 0) ||
				    (va < 0 && vb != (int)vb))
734
					return value_new_error (pos, gnumeric_err_NUM);
735 736 737 738 739 740

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

Arturo Espinosa's avatar
Arturo Espinosa committed
742
			default:
743
				break;
Arturo Espinosa's avatar
Arturo Espinosa committed
744 745
			}
		}
746
		return value_new_error (pos, _("Unknown operator"));
747

748 749 750
	case GNM_EXPR_OP_PERCENTAGE:
	case GNM_EXPR_OP_UNARY_NEG:
	case GNM_EXPR_OP_UNARY_PLUS:
751
	        /* Garantees that a != NULL */
752 753
		a = gnm_expr_eval (expr->unary.value, pos,
			flags & (~GNM_EXPR_EVAL_PERMIT_EMPTY));
Jody Goldberg's avatar
Jody Goldberg committed
754 755 756

		/* Handle implicit intersection */
		if (a->type == VALUE_CELLRANGE) {
757
			a = gnm_expr_implicit_intersection (pos, a);
Jody Goldberg's avatar
Jody Goldberg committed
758
			if (a == NULL)
759
				return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
760
		} else if (a->type == VALUE_ARRAY) {
761
			a = gnm_expr_array_intersection (a);
762 763
			if (a == NULL)
				return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
764 765
		}

766 767
		if (a->type == VALUE_ERROR)
			return a;
Jody Goldberg's avatar
Jody Goldberg committed
768

769
		if (expr->any.oper == GNM_EXPR_OP_UNARY_PLUS)
Jody Goldberg's avatar
Jody Goldberg committed
770 771
			return a;

772 773
		if (!VALUE_IS_NUMBER (a)){
			value_release (a);
774
			return value_new_error (pos, gnumeric_err_VALUE);
775
		}
776
		if (expr->any.oper == GNM_EXPR_OP_UNARY_NEG) {
Jody Goldberg's avatar
Jody Goldberg committed
777
			if (a->type == VALUE_INTEGER)
778
				res = value_new_int (-a->v_int.val);
Jody Goldberg's avatar
Jody Goldberg committed
779
			else if (a->type == VALUE_FLOAT)
780
				res = value_new_float (-a->v_float.val);
Jody Goldberg's avatar
Jody Goldberg committed
781
			else
782
				res = value_new_bool (!a->v_float.val);
783 784 785 786 787
			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
788
			res = value_new_float (value_get_as_float (a) / 100);
789 790 791
			VALUE_FMT (res) = style_format_default_percentage ();
			style_format_ref (VALUE_FMT (res));
		}
792
		value_release (a);
Morten Welinder's avatar
Morten Welinder committed
793
		return res;
794

795
	case GNM_EXPR_OP_CAT:
796
		a = expr_eval_real (expr->binary.value_a, pos, flags);
797
		if (a != NULL && a->type == VALUE_ERROR)
798
			return a;
799
		b = expr_eval_real (expr->binary.value_b, pos, flags);
800 801 802
		if (b != NULL && b->type == VALUE_ERROR) {
			if (a != NULL)
				value_release (a);
803
			return b;
804 805
		}

806 807 808 809 810 811 812 813 814 815 816 817 818 819
		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
820 821
			value_release (a);
			value_release (b);
822 823
		}

Morten Welinder's avatar
Morten Welinder committed
824
		return res;
Arturo Espinosa's avatar
Arturo Espinosa committed
825

826
	case GNM_EXPR_OP_FUNCALL: {
827 828
		FunctionEvalInfo ei;
		ei.pos = pos;
829
		ei.func_call = (GnmExprFunction const *)expr;
830

831
		/*if (flags & GNM_EXPR_EVAL_PERMIT_NON_SCALAR)*/
832 833
		return function_call_with_list (&ei, expr->func.arg_list);
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
834

835
	case GNM_EXPR_OP_NAME:
836 837 838
		if (expr->name.name->active)
			return expr_name_eval (expr->name.name, pos, flags);
		return value_new_error (pos, gnumeric_err_REF);