expr.c 51.2 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

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

32 33
/***************************************************************************/

34 35
GnmExpr const *
gnm_expr_new_constant (Value *v)
36
{
37
	GnmExprConstant *ans;
38

39
	ans = g_new (GnmExprConstant, 1);
40 41
	if (!ans)
		return NULL;
42
	gnm_expr_constant_init (ans, v);
43

44
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
45 46
}

47 48
GnmExpr const *
gnm_expr_new_error (char const *txt)
49
{
Jody Goldberg's avatar
Jody Goldberg committed
50
	FunctionDefinition *func;
51
	GnmExprList *args = NULL;
52

Jody Goldberg's avatar
Jody Goldberg committed
53 54
	if (strcmp (txt, gnumeric_err_NA) != 0) {
		func = func_lookup_by_name ("ERROR", NULL);
55 56
		args = gnm_expr_list_prepend (NULL,
			gnm_expr_new_constant (value_new_string (txt)));
Jody Goldberg's avatar
Jody Goldberg committed
57 58
	} else
		func = func_lookup_by_name ("NA", NULL);
59

Jody Goldberg's avatar
Jody Goldberg committed
60
	func_ref (func);
61
	return gnm_expr_new_funcall (func, args);
62 63
}

64 65
GnmExpr const *
gnm_expr_new_funcall (FunctionDefinition *func, GnmExprList *args)
66
{
67
	GnmExprFunction *ans;
Jody Goldberg's avatar
Jody Goldberg committed
68
	g_return_val_if_fail (func, NULL);
69

70
	ans = g_new (GnmExprFunction, 1);
71 72
	if (!ans)
		return NULL;
73

74
	ans->ref_count = 1;
75
	ans->oper = GNM_EXPR_OP_FUNCALL;
Jody Goldberg's avatar
Jody Goldberg committed
76
	func_ref (func);
Jody Goldberg's avatar
Jody Goldberg committed
77
	ans->func = func;;
78 79
	ans->arg_list = args;

80
	return (GnmExpr *)ans;
81
}
82

83 84
GnmExpr const *
gnm_expr_new_unary  (GnmExprOp op, GnmExpr const *e)
Morten Welinder's avatar
Morten Welinder committed
85
{
86
	GnmExprUnary *ans;
Morten Welinder's avatar
Morten Welinder committed
87

88
	ans = g_new (GnmExprUnary, 1);
89 90 91 92
	if (!ans)
		return NULL;

	ans->ref_count = 1;
93
	ans->oper = op;
94
	ans->value = e;
95

96
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
97 98 99
}


100 101
GnmExpr const *
gnm_expr_new_binary (GnmExpr const *l, GnmExprOp op, GnmExpr const *r)
Morten Welinder's avatar
Morten Welinder committed
102
{
103
	GnmExprBinary *ans;
Morten Welinder's avatar
Morten Welinder committed
104

105
	ans = g_new (GnmExprBinary, 1);
106 107
	if (!ans)
		return NULL;
108

109
	ans->ref_count = 1;
110
	ans->oper = op;
111 112
	ans->value_a = l;
	ans->value_b = r;
113

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

117 118
GnmExpr const *
gnm_expr_new_name (GnmNamedExpr *name,
119
		    Sheet *optional_scope, Workbook *optional_wb_scope)
Morten Welinder's avatar
Morten Welinder committed
120
{
121
	GnmExprName *ans;
Morten Welinder's avatar
Morten Welinder committed
122

123
	ans = g_new (GnmExprName, 1);
124 125
	if (!ans)
		return NULL;
126

127
	ans->ref_count = 1;
128
	ans->oper = GNM_EXPR_OP_NAME;
129
	ans->name = name;
130
	expr_name_ref (name);
131

132 133 134
	ans->optional_scope = optional_scope;
	ans->optional_wb_scope = optional_wb_scope;

135
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
136
}
137

138 139
GnmExpr const *
gnm_expr_new_cellref (CellRef const *cr)
140
{
141
	GnmExprCellRef *ans;
142

143
	ans = g_new (GnmExprCellRef, 1);
144 145
	if (!ans)
		return NULL;
146

147
	ans->ref_count = 1;
148
	ans->oper = GNM_EXPR_OP_CELLREF;
149 150
	ans->ref = *cr;

151
	return (GnmExpr *)ans;
152 153
}

154 155
GnmExpr const *
gnm_expr_new_array (int x, int y, int cols, int rows)
156
{
157
	GnmExprArray *ans;
158

159
	ans = g_new (GnmExprArray, 1);
160 161
	if (ans == NULL)
		return NULL;
162

163
	ans->ref_count = 1;
164
	ans->oper = GNM_EXPR_OP_ARRAY;
165 166 167 168
	ans->x = x;
	ans->y = y;
	ans->rows = rows;
	ans->cols = cols;
169 170
	ans->corner.value = NULL;
	ans->corner.expr = NULL;
171
	return (GnmExpr *)ans;
172 173
}

174 175
GnmExpr const *
gnm_expr_new_set (GnmExprList *set)
176
{
177
	GnmExprSet *ans;
178

179
	ans = g_new (GnmExprSet, 1);
180 181
	if (!ans)
		return NULL;
182

183
	ans->ref_count = 1;
184
	ans->oper = GNM_EXPR_OP_SET;
185
	ans->set = set;
186

187
	return (GnmExpr *)ans;
188 189
}

190
static Cell *
191
expr_array_corner (GnmExpr const *expr,
192
			Sheet const *sheet, CellPos const *pos)
193
{
194 195
	Cell *corner = sheet_cell_get (sheet,
		pos->col - expr->array.x, pos->row - expr->array.y);
196

197
	/* Sanity check incase the corner gets removed for some reason */
198
	g_return_val_if_fail (corner != NULL, NULL);
199
	g_return_val_if_fail (cell_has_expr (corner), NULL);
200
	g_return_val_if_fail (corner->base.expression != (void *)0xdeadbeef, NULL);
201
	g_return_val_if_fail (corner->base.expression->any.oper == GNM_EXPR_OP_ARRAY, NULL);
202 203
	g_return_val_if_fail (corner->base.expression->array.x == 0, NULL);
	g_return_val_if_fail (corner->base.expression->array.y == 0, NULL);
204

205
	return corner;
206 207
}

208 209 210
/**
 * gnm_expr_ref:
 * Increments the ref_count for an expression node.
Arturo Espinosa's avatar
Arturo Espinosa committed
211
 */
212
void
213
gnm_expr_ref (GnmExpr const *expr)
214
{
215 216
	g_return_if_fail (expr != NULL);
	g_return_if_fail (expr->any.ref_count > 0);
217

218
	((GnmExpr *)expr)->any.ref_count++;
Arturo Espinosa's avatar
Arturo Espinosa committed
219 220 221
}

static void
222
do_gnm_expr_unref (GnmExpr const *expr)
Arturo Espinosa's avatar
Arturo Espinosa committed
223
{
224
	if (--((GnmExpr *)expr)->any.ref_count > 0)
Morten Welinder's avatar
Morten Welinder committed
225 226
		return;

227 228
	switch (expr->any.oper) {
	case GNM_EXPR_OP_CELLREF:
Arturo Espinosa's avatar
Arturo Espinosa committed
229
		break;
230

231 232
	case GNM_EXPR_OP_CONSTANT:
		value_release ((Value *)expr->constant.value);
Arturo Espinosa's avatar
Arturo Espinosa committed
233
		break;
234

235 236
	case GNM_EXPR_OP_FUNCALL:
		gnm_expr_list_unref (expr->func.arg_list);
237
		func_unref (expr->func.func);
Arturo Espinosa's avatar
Arturo Espinosa committed
238 239
		break;

240
	case GNM_EXPR_OP_NAME:
241
		expr_name_unref (expr->name.name);
Michael Meeks's avatar
Michael Meeks committed
242 243
		break;

244 245 246
	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
247 248
		break;

249 250
	case GNM_EXPR_OP_ANY_UNARY:
		do_gnm_expr_unref (expr->unary.value);
Arturo Espinosa's avatar
Arturo Espinosa committed
251
		break;
252
	case GNM_EXPR_OP_ARRAY:
253 254 255
		if (expr->array.x == 0 && expr->array.y == 0) {
			if (expr->array.corner.value)
				value_release (expr->array.corner.value);
256
			do_gnm_expr_unref (expr->array.corner.expr);
257
		}
258
		break;
259 260
	case GNM_EXPR_OP_SET:
		gnm_expr_list_unref (expr->set.set);
261 262
		break;

263
	default:
264
		g_warning ("do_gnm_expr_unref error\n");
265
		break;
Arturo Espinosa's avatar
Arturo Espinosa committed
266
	}
267

268
	g_free ((gpointer)expr);
269 270
}

Morten Welinder's avatar
Morten Welinder committed
271
/*
272 273
 * gnm_expr_unref:
 * Decrements the ref_count for part of a expression.  (All trees are expected
Morten Welinder's avatar
Morten Welinder committed
274 275 276
 * 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.)
 */
277
void
278
gnm_expr_unref (GnmExpr const *expr)
279
{
280 281
	g_return_if_fail (expr != NULL);
	g_return_if_fail (expr->any.ref_count > 0);
282

283
	if (expr->any.ref_count == 1)
284
		do_gnm_expr_unref (expr);
285
	else
286
		((GnmExpr *)expr)->any.ref_count--;
287 288
}

Jody Goldberg's avatar
Jody Goldberg committed
289
/**
290
 * gnm_expr_is_shared : Returns TRUE if the reference count
Jody Goldberg's avatar
Jody Goldberg committed
291 292 293
 *   for the supplied expression is > 1
 */
gboolean
294
gnm_expr_is_shared (GnmExpr const *expr)
Jody Goldberg's avatar
Jody Goldberg committed
295
{
296
	g_return_val_if_fail (expr != NULL, FALSE);
Jody Goldberg's avatar
Jody Goldberg committed
297

298
	return (expr->any.ref_count > 1);
Jody Goldberg's avatar
Jody Goldberg committed
299 300
}

Jody Goldberg's avatar
Jody Goldberg committed
301
/**
302
 * gnm_expr_equal : Returns TRUE if the supplied expressions are exactly the
Jody Goldberg's avatar
Jody Goldberg committed
303 304 305 306 307
 *   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
308
gnm_expr_equal (GnmExpr const *a, GnmExpr const *b)
Jody Goldberg's avatar
Jody Goldberg committed
309 310 311 312 313 314 315 316 317 318 319
{
	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) {
320 321 322
	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
323

324 325
	case GNM_EXPR_OP_ANY_UNARY:
		return gnm_expr_equal (a->unary.value, b->unary.value);
Jody Goldberg's avatar
Jody Goldberg committed
326

327
	case GNM_EXPR_OP_FUNCALL:
328
		return (a->func.func == b->func.func) &&
329
			gnm_expr_list_equal (a->func.arg_list, b->func.arg_list);
Jody Goldberg's avatar
Jody Goldberg committed
330

331
	case GNM_EXPR_OP_NAME:
Jody Goldberg's avatar
Jody Goldberg committed
332 333
		return a->name.name == b->name.name;

334 335
	case GNM_EXPR_OP_CELLREF:
		return cellref_equal (&a->cellref.ref, &b->cellref.ref);
Jody Goldberg's avatar
Jody Goldberg committed
336

337
	case GNM_EXPR_OP_CONSTANT: {
Jody Goldberg's avatar
Jody Goldberg committed
338 339 340 341 342 343 344 345 346 347 348 349 350
		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;
	}

351 352 353
	case GNM_EXPR_OP_ARRAY: {
		GnmExprArray const *aa = &a->array;
		GnmExprArray const *ab = &b->array;
Jody Goldberg's avatar
Jody Goldberg committed
354 355 356 357 358

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

362 363
	case GNM_EXPR_OP_SET:
		return gnm_expr_list_equal (a->set.set, b->set.set);
364

Jody Goldberg's avatar
Jody Goldberg committed
365 366 367 368 369 370 371
	default :
		g_assert_not_reached ();
	}

	return FALSE;
}

Jody Goldberg's avatar
Jody Goldberg committed
372
/**
373
 * gnm_expr_implicit_intersection :
Jody Goldberg's avatar
Jody Goldberg committed
374 375
 * @ei: EvalInfo containing valid fd!
 * @v: a VALUE_CELLRANGE
376
 *
377 378 379 380 381
 * 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
382 383 384
 *
 * Always release the value passed in.
 *
385
 * Return value:
Jody Goldberg's avatar
Jody Goldberg committed
386 387 388 389
 *     If the intersection succeeded return a duplicate of the value
 *     at the intersection point.  This value needs to be freed.
 **/
Value *
390
gnm_expr_implicit_intersection (EvalPos const *pos, Value *v)
Jody Goldberg's avatar
Jody Goldberg committed
391 392
{
	Value *res = NULL;
393 394 395 396
	Range rng;
	Sheet *start_sheet, *end_sheet;

	/* handle inverted ranges */
Jody Goldberg's avatar
Jody Goldberg committed
397
	value_cellrange_normalize (pos, v, &start_sheet, &end_sheet, &rng);
398 399 400

	if (start_sheet == end_sheet) {
		if (rng.start.row == rng.end.row) {
Jody Goldberg's avatar
Jody Goldberg committed
401
			int const c = pos->eval.col;
Jody Goldberg's avatar
Jody Goldberg committed
402 403 404 405 406 407
			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
408 409
		}

410
		if (rng.start.col == rng.end.col) {
Jody Goldberg's avatar
Jody Goldberg committed
411
			int const r = pos->eval.row;
Jody Goldberg's avatar
Jody Goldberg committed
412 413 414 415 416 417
			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
418 419 420 421 422 423
		}
	}
	value_release (v);
	return res;
}

424
/**
425
 * gnm_expr_array_intersection :
426 427 428 429 430 431 432 433 434 435 436 437 438
 * @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 *
439
gnm_expr_array_intersection (Value *a)
440 441 442 443 444 445
{
	Value *tmp = value_duplicate (a->v_array.vals [0][0]);
	value_release (a);
	return tmp;
}

Jody Goldberg's avatar
Jody Goldberg committed
446 447
static Value *
cb_range_eval (Sheet *sheet, int col, int row, Cell *cell, void *ignore)
448
{
Jody Goldberg's avatar
Jody Goldberg committed
449 450
	cell_eval (cell);
	return NULL;
451 452
}

453
static Value *
454 455
expr_eval_real (GnmExpr const *expr, EvalPos const *pos,
		GnmExprEvalFlags flags)
Arturo Espinosa's avatar
Arturo Espinosa committed
456
{
457
	Value *res = NULL, *a = NULL, *b = NULL;
458

459
	g_return_val_if_fail (expr != NULL, NULL);
460
	g_return_val_if_fail (pos != NULL, NULL);
461

462
	switch (expr->any.oper){
463 464 465 466 467 468
	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: {
469
		ValueCompare comp;
470

471
		a = expr_eval_real (expr->binary.value_a, pos, flags);
Jody Goldberg's avatar
Jody Goldberg committed
472 473
		if (a != NULL) {
			if (a->type == VALUE_CELLRANGE) {
474
				a = gnm_expr_implicit_intersection (pos, a);
Jody Goldberg's avatar
Jody Goldberg committed
475
				if (a == NULL)
476
					return value_new_error (pos, gnumeric_err_VALUE);
477
			} else if (a->type == VALUE_ARRAY) {
478
				a = gnm_expr_array_intersection (a);
479 480
				if (a == NULL)
					return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
481 482 483
			} else if (a->type == VALUE_ERROR)
				return a;
		}
Morten Welinder's avatar
Morten Welinder committed
484

485
		b = expr_eval_real (expr->binary.value_b, pos, flags);
Jody Goldberg's avatar
Jody Goldberg committed
486 487 488
		if (b != NULL) {
			Value *res = NULL;
			if (b->type == VALUE_CELLRANGE) {
489
				b = gnm_expr_implicit_intersection (pos, b);
Jody Goldberg's avatar
Jody Goldberg committed
490
				if (b == NULL)
491
					res = value_new_error (pos, gnumeric_err_VALUE);
492
			} else if (b->type == VALUE_ARRAY) {
493
				b = gnm_expr_array_intersection (b);
494 495
				if (b == NULL)
					return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
496 497 498 499 500 501 502 503
			} 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
504
		}
505

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

508 509 510 511
		if (a != NULL)
			value_release (a);
		if (b != NULL)
			value_release (b);
512

Michael Meeks's avatar
Michael Meeks committed
513
		if (comp == TYPE_MISMATCH) {
514 515 516 517
			/* TODO TODO TODO : Make error more informative
			 *    regarding what is comparing to what
			 */
			/* For equality comparisons even errors are ok */
518
			if (expr->any.oper == GNM_EXPR_OP_EQUAL)
519
				return value_new_bool (FALSE);
520
			if (expr->any.oper == GNM_EXPR_OP_NOT_EQUAL)
521 522
				return value_new_bool (TRUE);

523
			return value_new_error (pos, gnumeric_err_VALUE);
524
		}
525

526
		switch (expr->any.oper) {
527
		case GNM_EXPR_OP_EQUAL:
528
			res = value_new_bool (comp == IS_EQUAL);
Arturo Espinosa's avatar
Arturo Espinosa committed
529 530
			break;

531
		case GNM_EXPR_OP_GT:
532
			res = value_new_bool (comp == IS_GREATER);
Arturo Espinosa's avatar
Arturo Espinosa committed
533 534
			break;

535
		case GNM_EXPR_OP_LT:
536
			res = value_new_bool (comp == IS_LESS);
Arturo Espinosa's avatar
Arturo Espinosa committed
537 538
			break;

539
		case GNM_EXPR_OP_NOT_EQUAL:
540
			res = value_new_bool (comp != IS_EQUAL);
Arturo Espinosa's avatar
Arturo Espinosa committed
541 542
			break;

543
		case GNM_EXPR_OP_LTE:
544
			res = value_new_bool (comp != IS_GREATER);
Arturo Espinosa's avatar
Arturo Espinosa committed
545 546
			break;

547
		case GNM_EXPR_OP_GTE:
548
			res = value_new_bool (comp != IS_LESS);
Arturo Espinosa's avatar
Arturo Espinosa committed
549
			break;
550

Arturo Espinosa's avatar
Arturo Espinosa committed
551
		default:
552
			g_assert_not_reached ();
553
			res = value_new_error (pos,
554
						_("Internal type error"));
Arturo Espinosa's avatar
Arturo Espinosa committed
555
		}
Morten Welinder's avatar
Morten Welinder committed
556
		return res;
Arturo Espinosa's avatar
Arturo Espinosa committed
557
	}
558

559 560 561 562 563
	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:
564 565 566 567 568 569 570 571 572
		/*
		 * 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
		 */

573
	        /* Guarantees a != NULL */
574 575
		a = gnm_expr_eval (expr->binary.value_a, pos,
			       flags & (~GNM_EXPR_EVAL_PERMIT_EMPTY));
Jody Goldberg's avatar
Jody Goldberg committed
576 577 578

		/* Handle implicit intersection */
		if (a->type == VALUE_CELLRANGE) {
579
			a = gnm_expr_implicit_intersection (pos, a);
Jody Goldberg's avatar
Jody Goldberg committed
580
			if (a == NULL)
581
				return value_new_error (pos, gnumeric_err_VALUE);
582
		} else if (a->type == VALUE_ARRAY) {
583
			a = gnm_expr_array_intersection (a);
584 585
			if (a == NULL)
				return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
586 587
		}

588 589
		/* 1) Error from A */
		if (a->type == VALUE_ERROR)
590
			return value_error_set_pos (&a->v_err, pos);
591

592
		/* 2) #!VALUE error if A is not a number */
593
		if (a->type == VALUE_STRING) {
594
			Value *tmp = format_match_number (a->v_str.val->str, NULL);
595 596 597 598 599 600

			value_release (a);
			if (tmp == NULL)
				return value_new_error (pos, gnumeric_err_VALUE);
			a = tmp;
		} else if (!VALUE_IS_NUMBER (a)) {
601
			value_release (a);
602
			return value_new_error (pos, gnumeric_err_VALUE);
603 604
		}

605
	        /* Guarantees that b != NULL */
606 607
		b = gnm_expr_eval (expr->binary.value_b, pos,
			       flags & (~GNM_EXPR_EVAL_PERMIT_EMPTY));
Arturo Espinosa's avatar
Arturo Espinosa committed
608

Jody Goldberg's avatar
Jody Goldberg committed
609 610
		/* Handle implicit intersection */
		if (b->type == VALUE_CELLRANGE) {
611
			b = gnm_expr_implicit_intersection (pos, a);
Jody Goldberg's avatar
Jody Goldberg committed
612
			if (b == NULL)
613
				return value_new_error (pos, gnumeric_err_VALUE);
614
		} else if (b->type == VALUE_ARRAY) {
615
			b = gnm_expr_array_intersection (b);
616 617
			if (b == NULL)
				return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
618 619
		}

620 621
		/* 3) Error from B */
		if (b->type == VALUE_ERROR) {
622
			value_release (a);
623
			return value_error_set_pos (&b->v_err, pos);
Arturo Espinosa's avatar
Arturo Espinosa committed
624
		}
625

626
		/* 4) #!VALUE error if B is not a number */
627
		if (b->type == VALUE_STRING) {
628
			Value *tmp = format_match_number (b->v_str.val->str, NULL);
629 630 631 632 633 634 635 636

			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)) {
637 638
			value_release (a);
			value_release (b);
639
			return value_new_error (pos, gnumeric_err_VALUE);
Arturo Espinosa's avatar
Arturo Espinosa committed
640
		}
641

642
		if (a->type != VALUE_FLOAT && b->type != VALUE_FLOAT){
Morten Welinder's avatar
Morten Welinder committed
643
			int ia = value_get_as_int (a);
644
			int ib = value_get_as_int (b);
645
			gnum_float dres;
646 647
			int ires;

Morten Welinder's avatar
Morten Welinder committed
648 649
			value_release (a);
			value_release (b);
650

651 652
			/* FIXME: we could use simple (cheap) heuristics to
			   catch most cases where overflow will not happen.  */
653
			switch (expr->any.oper){
654
			case GNM_EXPR_OP_ADD:
655
				dres = (gnum_float)ia + (gnum_float)ib;
656 657 658 659
				ires = (int)dres;
				if (dres == ires)
					return value_new_int (ires);
				else
660
					return value_new_float ((gnum_float) dres);
661

662
			case GNM_EXPR_OP_SUB:
663
				dres = (gnum_float)ia - (gnum_float)ib;
664 665 666 667
				ires = (int)dres;
				if (dres == ires)
					return value_new_int (ires);
				else
668
					return value_new_float ((gnum_float) dres);
669

670
			case GNM_EXPR_OP_MULT:
671
				dres = (gnum_float)ia * (gnum_float)ib;
672 673 674 675
				ires = (int)dres;
				if (dres == ires)
					return value_new_int (ires);
				else
676
					return value_new_float ((gnum_float) dres);
Arturo Espinosa's avatar
Arturo Espinosa committed
677

678
			case GNM_EXPR_OP_DIV:
679
				if (ib == 0)
680
					return value_new_error (pos, gnumeric_err_DIV0);
681
				dres = (gnum_float)ia / (gnum_float)ib;
682 683 684 685
				ires = (int)dres;
				if (dres == ires)
					return value_new_int (ires);
				else
686
					return value_new_float ((gnum_float) dres);
687

688
			case GNM_EXPR_OP_EXP:
689
				if (ia == 0 && ib <= 0)
690
					return value_new_error (pos, gnumeric_err_NUM);
691
				dres = powgnum ((gnum_float)ia, (gnum_float)ib);
692 693 694 695
				ires = (int)dres;
				if (dres == ires)
					return value_new_int (ires);
				else
696
					return value_new_float ((gnum_float) dres);
697

Arturo Espinosa's avatar
Arturo Espinosa committed
698
			default:
699
				abort ();
Arturo Espinosa's avatar
Arturo Espinosa committed
700 701
			}
		} else {
702 703
			gnum_float const va = value_get_as_float (a);
			gnum_float const vb = value_get_as_float (b);
704 705
			value_release (a);
			value_release (b);
706

707
			switch (expr->any.oper){
708
			case GNM_EXPR_OP_ADD:
Arturo Espinosa's avatar
Arturo Espinosa committed
709
				return value_new_float (va + vb);
710

711
			case GNM_EXPR_OP_SUB:
Arturo Espinosa's avatar
Arturo Espinosa committed
712
				return value_new_float (va - vb);
713

714
			case GNM_EXPR_OP_MULT:
Arturo Espinosa's avatar
Arturo Espinosa committed
715
				return value_new_float (va * vb);
716

717
			case GNM_EXPR_OP_DIV:
718
				return (vb == 0.0)
719
				    ? value_new_error (pos,
720
						       gnumeric_err_DIV0)
Arturo Espinosa's avatar
Arturo Espinosa committed
721
				    : value_new_float (va / vb);
722

723
			case GNM_EXPR_OP_EXP:
724 725
				if ((va == 0 && vb <= 0) ||
				    (va < 0 && vb != (int)vb))
726
					return value_new_error (pos, gnumeric_err_NUM);
727
				return value_new_float (powgnum (va, vb));
728

Arturo Espinosa's avatar
Arturo Espinosa committed
729
			default:
730
				break;
Arturo Espinosa's avatar
Arturo Espinosa committed
731 732
			}
		}
733
		return value_new_error (pos, _("Unknown operator"));
734

735 736 737
	case GNM_EXPR_OP_PERCENTAGE:
	case GNM_EXPR_OP_UNARY_NEG:
	case GNM_EXPR_OP_UNARY_PLUS:
738
	        /* Garantees that a != NULL */
739 740
		a = gnm_expr_eval (expr->unary.value, pos,
			flags & (~GNM_EXPR_EVAL_PERMIT_EMPTY));
Jody Goldberg's avatar
Jody Goldberg committed
741 742 743

		/* Handle implicit intersection */
		if (a->type == VALUE_CELLRANGE) {
744
			a = gnm_expr_implicit_intersection (pos, a);
Jody Goldberg's avatar
Jody Goldberg committed
745
			if (a == NULL)
746
				return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
747
		} else if (a->type == VALUE_ARRAY) {
748
			a = gnm_expr_array_intersection (a);
749 750
			if (a == NULL)
				return value_new_error (pos, gnumeric_err_VALUE);
Jody Goldberg's avatar
Jody Goldberg committed
751 752
		}

753 754
		if (a->type == VALUE_ERROR)
			return a;
Jody Goldberg's avatar
Jody Goldberg committed
755

756
		if (expr->any.oper == GNM_EXPR_OP_UNARY_PLUS)
Jody Goldberg's avatar
Jody Goldberg committed
757 758
			return a;

759 760
		if (!VALUE_IS_NUMBER (a)){
			value_release (a);
761
			return value_new_error (pos, gnumeric_err_VALUE);
762
		}
763
		if (expr->any.oper == GNM_EXPR_OP_UNARY_NEG) {
Jody Goldberg's avatar
Jody Goldberg committed
764
			if (a->type == VALUE_INTEGER)
765
				res = value_new_int (-a->v_int.val);
Jody Goldberg's avatar
Jody Goldberg committed
766
			else if (a->type == VALUE_FLOAT)
767
				res = value_new_float (-a->v_float.val);
Jody Goldberg's avatar
Jody Goldberg committed
768
			else
769
				res = value_new_bool (!a->v_float.val);
770 771 772 773 774
			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
775
			res = value_new_float (value_get_as_float (a) / 100);
776 777 778
			VALUE_FMT (res) = style_format_default_percentage ();
			style_format_ref (VALUE_FMT (res));
		}
779
		value_release (a);
Morten Welinder's avatar
Morten Welinder committed
780
		return res;
781

782
	case GNM_EXPR_OP_CAT:
783
		a = expr_eval_real (expr->binary.value_a, pos, flags);
784
		if (a != NULL && a->type == VALUE_ERROR)
785
			return a;
786
		b = expr_eval_real (expr->binary.value_b, pos, flags);
787 788 789
		if (b != NULL && b->type == VALUE_ERROR) {
			if (a != NULL)
				value_release (a);
790
			return b;
791 792
		}

793 794 795 796 797 798 799 800 801 802 803 804 805 806
		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
807 808
			value_release (a);
			value_release (b);
809 810
		}

Morten Welinder's avatar
Morten Welinder committed
811
		return res;
Arturo Espinosa's avatar
Arturo Espinosa committed
812

813
	case GNM_EXPR_OP_FUNCALL: {
814 815
		FunctionEvalInfo ei;
		ei.pos = pos;
816
		ei.func_call = (GnmExprFunction const *)expr;
817

818
		/*if (flags & GNM_EXPR_EVAL_PERMIT_NON_SCALAR)*/
819 820
		return function_call_with_list (&ei, expr->func.arg_list);
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
821

822
	case GNM_EXPR_OP_NAME:
823 824 825
		if (expr->name.name->active)
			return expr_name_eval (expr->name.name, pos, flags);
		return value_new_error (pos, gnumeric_err_REF);