expr.c 80.1 KB
Newer Older
1
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
Miguel de Icaza's avatar
Miguel de Icaza committed
2
/*
3
 * expr.c : Expression evaluation in Gnumeric
Miguel de Icaza's avatar
Miguel de Icaza committed
4
 *
5
 * Copyright (C) 2001-2006 Jody Goldberg (jody@gnome.org)
6
 * Copyright (C) 1998-2000 Miguel de Icaza (miguel@gnu.org)
Morten Welinder's avatar
Morten Welinder committed
7
 * Copyright (C) 2000-2009 Morten Welinder (terra@gnome.org)
8 9 10 11 12 13 14 15 16 17 18 19
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
J.H.M. Dassen (Ray)'s avatar
J.H.M. Dassen (Ray) committed
20
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
21
 * USA
Miguel de Icaza's avatar
Miguel de Icaza committed
22
 */
23
#include <gnumeric-config.h>
24
#include <glib/gi18n-lib.h>
25
#include "gnumeric.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
26
#include "expr.h"
27

28
#include "expr-impl.h"
29
#include "expr-name.h"
30
#include "dependent.h"
31
#include "application.h"
32
#include "func.h"
Jody Goldberg's avatar
Jody Goldberg committed
33
#include "cell.h"
Jody Goldberg's avatar
Jody Goldberg committed
34
#include "sheet.h"
35
#include "value.h"
36
#include "parse-util.h"
37
#include "ranges.h"
38
#include "number-match.h"
Jody Goldberg's avatar
Jody Goldberg committed
39
#include "workbook-priv.h"
Jeffrey Stedfast's avatar
Jeffrey Stedfast committed
40
#include "gutils.h"
41
#include "parse-util.h"
42
#include "mathfunc.h"
43

44 45
#include <math.h>
#include <string.h>
Jody Goldberg's avatar
Jody Goldberg committed
46
#include <stdlib.h>
47
#include <goffice/utils/go-locale.h>
48
#include <goffice/utils/go-format.h>
Morten Welinder's avatar
Morten Welinder committed
49
#include <goffice/utils/go-glib-extras.h>
50

51 52 53 54 55 56 57 58 59
/*
 * 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
60 61
/* Memory pools for expressions.  */
static GOMemChunk *expression_pool_small, *expression_pool_big;
62 63
#define CHUNK_ALLOC(T,p) ((T*)go_mem_chunk_alloc (p))
#define CHUNK_FREE(p,v) go_mem_chunk_free ((p), (v))
64 65 66 67 68
#else
#define CHUNK_ALLOC(T,c) g_new (T,1)
#define CHUNK_FREE(p,v) g_free ((v))
#endif

69 70
/***************************************************************************/

Jody Goldberg's avatar
Jody Goldberg committed
71 72 73 74 75 76
/**
 * gnm_expr_new_constant :
 * @v :
 *
 * Absorbs the value.
 **/
77
GnmExpr const *
Jody Goldberg's avatar
Jody Goldberg committed
78
gnm_expr_new_constant (GnmValue *v)
79
{
80
	GnmExprConstant *ans;
81

82
	ans = CHUNK_ALLOC (GnmExprConstant, expression_pool_small);
83 84
	if (!ans)
		return NULL;
85
	gnm_expr_constant_init (ans, v);
86

87
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
88 89
}

Jody Goldberg's avatar
Jody Goldberg committed
90 91
/***************************************************************************/

92 93
static GnmExpr const *
gnm_expr_new_funcallv (GnmFunc *func, int argc, GnmExprConstPtr *argv)
94
{
95
	GnmExprFunction *ans;
Jody Goldberg's avatar
Jody Goldberg committed
96
	g_return_val_if_fail (func, NULL);
97

98
	ans = CHUNK_ALLOC (GnmExprFunction, expression_pool_small);
99

100
	ans->oper = GNM_EXPR_OP_FUNCALL;
Jody Goldberg's avatar
Jody Goldberg committed
101
	gnm_func_ref (func);
102
	ans->func = func;
103 104
	ans->argc = argc;
	ans->argv = argv;
105

106
	return (GnmExpr *)ans;
107
}
108

109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
GnmExpr const *
gnm_expr_new_funcall (GnmFunc *func, GnmExprList *arg_list)
{
	GnmExprList *arg_list0 = arg_list;
	int argc = gnm_expr_list_length (arg_list);
	GnmExprConstPtr *argv = argc ? g_new (GnmExprConstPtr, argc) : NULL;
	int i;

	for (i = 0; arg_list; i++, arg_list = arg_list->next)
		argv[i] = arg_list->data;
	gnm_expr_list_free (arg_list0);

	return gnm_expr_new_funcallv (func, argc, argv);
}

Morten Welinder's avatar
Morten Welinder committed
124 125 126 127
GnmExpr const *
gnm_expr_new_funcall1 (GnmFunc *func,
		       GnmExpr const *arg0)
{
128 129 130
	GnmExprConstPtr *argv = g_new (GnmExprConstPtr, 1);
	argv[0] = arg0;
	return gnm_expr_new_funcallv (func, 1, argv);
Morten Welinder's avatar
Morten Welinder committed
131 132 133 134 135 136 137
}

GnmExpr const *
gnm_expr_new_funcall2 (GnmFunc *func,
		       GnmExpr const *arg0,
		       GnmExpr const *arg1)
{
138 139 140 141
	GnmExprConstPtr *argv = g_new (GnmExprConstPtr, 2);
	argv[0] = arg0;
	argv[1] = arg1;
	return gnm_expr_new_funcallv (func, 2, argv);
Morten Welinder's avatar
Morten Welinder committed
142 143 144 145 146 147 148 149
}

GnmExpr const *
gnm_expr_new_funcall3 (GnmFunc *func,
		       GnmExpr const *arg0,
		       GnmExpr const *arg1,
		       GnmExpr const *arg2)
{
150 151 152 153 154
	GnmExprConstPtr *argv = g_new (GnmExprConstPtr, 3);
	argv[0] = arg0;
	argv[1] = arg1;
	argv[2] = arg2;
	return gnm_expr_new_funcallv (func, 3, argv);
Morten Welinder's avatar
Morten Welinder committed
155 156
}

157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
GnmExpr const *
gnm_expr_new_funcall4 (GnmFunc *func,
		       GnmExpr const *arg0,
		       GnmExpr const *arg1,
		       GnmExpr const *arg2,
		       GnmExpr const *arg3)
{
	GnmExprConstPtr *argv = g_new (GnmExprConstPtr, 4);
	argv[0] = arg0;
	argv[1] = arg1;
	argv[2] = arg2;
	argv[3] = arg3;
	return gnm_expr_new_funcallv (func, 4, argv);
}

Morten Welinder's avatar
Morten Welinder committed
172

Jody Goldberg's avatar
Jody Goldberg committed
173 174
/***************************************************************************/

175 176
GnmExpr const *
gnm_expr_new_unary  (GnmExprOp op, GnmExpr const *e)
Morten Welinder's avatar
Morten Welinder committed
177
{
178
	GnmExprUnary *ans;
Morten Welinder's avatar
Morten Welinder committed
179

180
	ans = CHUNK_ALLOC (GnmExprUnary, expression_pool_small);
181 182 183
	if (!ans)
		return NULL;

184
	ans->oper = op;
185
	ans->value = e;
186

187
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
188 189
}

Jody Goldberg's avatar
Jody Goldberg committed
190 191
/***************************************************************************/

192 193
GnmExpr const *
gnm_expr_new_binary (GnmExpr const *l, GnmExprOp op, GnmExpr const *r)
Morten Welinder's avatar
Morten Welinder committed
194
{
195
	GnmExprBinary *ans;
Morten Welinder's avatar
Morten Welinder committed
196

197
	ans = CHUNK_ALLOC (GnmExprBinary, expression_pool_small);
198 199
	if (!ans)
		return NULL;
200

201
	ans->oper = op;
202 203
	ans->value_a = l;
	ans->value_b = r;
204

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

Jody Goldberg's avatar
Jody Goldberg committed
208 209
/***************************************************************************/

210 211
GnmExpr const *
gnm_expr_new_name (GnmNamedExpr *name,
212
		   Sheet *optional_scope, Workbook *optional_wb_scope)
Morten Welinder's avatar
Morten Welinder committed
213
{
214
	GnmExprName *ans;
Morten Welinder's avatar
Morten Welinder committed
215

216
	ans = CHUNK_ALLOC (GnmExprName, expression_pool_big);
217 218
	if (!ans)
		return NULL;
219

220
	ans->oper = GNM_EXPR_OP_NAME;
221
	ans->name = name;
222
	expr_name_ref (name);
223

224 225 226
	ans->optional_scope = optional_scope;
	ans->optional_wb_scope = optional_wb_scope;

227
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
228
}
229

Jody Goldberg's avatar
Jody Goldberg committed
230 231
/***************************************************************************/

232
GnmExpr const *
Jody Goldberg's avatar
Jody Goldberg committed
233
gnm_expr_new_cellref (GnmCellRef const *cr)
234
{
235
	GnmExprCellRef *ans;
236

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

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

244
	return (GnmExpr *)ans;
245 246
}

Jody Goldberg's avatar
Jody Goldberg committed
247 248 249
/***************************************************************************/

/**
250
 * gnm_expr_new_array_corner :
Jody Goldberg's avatar
Jody Goldberg committed
251 252 253 254 255 256
 * @cols :
 * @rows :
 * @expr : optionally NULL.
 *
 * Absorb a referernce to @expr if it is non NULL.
 **/
257
static GnmExpr const *
258
gnm_expr_new_array_corner(int cols, int rows, GnmExpr const *expr)
259
{
260
	GnmExprArrayCorner *ans;
261

262
	ans = CHUNK_ALLOC (GnmExprArrayCorner, expression_pool_big);
263 264
	if (ans == NULL)
		return NULL;
265

266
	ans->oper = GNM_EXPR_OP_ARRAY_CORNER;
267 268
	ans->rows = rows;
	ans->cols = cols;
269 270 271 272 273
	ans->value = NULL;
	ans->expr = expr;
	return (GnmExpr *)ans;
}

274
static GnmExpr const *
275 276 277 278
gnm_expr_new_array_elem  (int x, int y)
{
	GnmExprArrayElem *ans;

279
	ans = CHUNK_ALLOC (GnmExprArrayElem, expression_pool_small);
280 281 282
	if (ans == NULL)
		return NULL;

283
	ans->oper = GNM_EXPR_OP_ARRAY_ELEM;
284 285
	ans->x = x;
	ans->y = y;
286
	return (GnmExpr *)ans;
287 288
}

Jody Goldberg's avatar
Jody Goldberg committed
289 290
/***************************************************************************/

291 292
static GnmExpr const *
gnm_expr_new_setv (int argc, GnmExprConstPtr *argv)
Jody Goldberg's avatar
Jody Goldberg committed
293
{
294 295
	GnmExprSet *ans = CHUNK_ALLOC (GnmExprSet, expression_pool_small);

296
	ans->oper = GNM_EXPR_OP_SET;
297 298 299 300
	ans->argc = argc;
	ans->argv = argv;

	return (GnmExpr *)ans;
Jody Goldberg's avatar
Jody Goldberg committed
301 302
}

303 304
GnmExpr const *
gnm_expr_new_set (GnmExprList *set)
305
{
306 307 308
	int i, argc;
	GnmExprConstPtr *argv;
	GnmExprList *set0 = set;
309

310 311 312 313 314
	argc = gnm_expr_list_length (set);
	argv = argc ? g_new (GnmExprConstPtr, argc) : NULL;
	for (i = 0; set; i++, set = set->next)
		argv[i] = set->data;
	gnm_expr_list_free (set0);
315

316
	return gnm_expr_new_setv (argc, argv);
317 318
}

Jody Goldberg's avatar
Jody Goldberg committed
319
/***************************************************************************/
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353

/**
 * gnm_expr_new_range_ctor:
 * @l: start range
 * @r: end range
 *
 * This function builds a range constructor or something simpler,
 * but equivalent, if the arguments allow it. 
 *
 * Note: this takes ownership of @l and @r and may delete them.
 **/
GnmExpr const *
gnm_expr_new_range_ctor (GnmExpr const *l, GnmExpr const *r)
{
	GnmValue *v;

	g_return_val_if_fail (l != NULL, NULL);
	g_return_val_if_fail (r != NULL, NULL);

	if (GNM_EXPR_GET_OPER (l) != GNM_EXPR_OP_CELLREF)
		goto fallback;
	if (GNM_EXPR_GET_OPER (r) != GNM_EXPR_OP_CELLREF)
		goto fallback;

	v = value_new_cellrange_unsafe (&l->cellref.ref, &r->cellref.ref);
	gnm_expr_free (l);
	gnm_expr_free (r);
	return gnm_expr_new_constant (v);

 fallback:
	return gnm_expr_new_binary (l, GNM_EXPR_OP_RANGE_CTOR, r);
}

/***************************************************************************/
Jody Goldberg's avatar
Jody Goldberg committed
354

355 356
GnmExpr const *
gnm_expr_copy (GnmExpr const *expr)
357
{
358 359
	g_return_val_if_fail (expr != NULL, NULL);

360 361 362 363 364 365 366 367
	switch (GNM_EXPR_GET_OPER (expr)) {
	case GNM_EXPR_OP_RANGE_CTOR:
	case GNM_EXPR_OP_INTERSECT:
	case GNM_EXPR_OP_ANY_BINARY:
		return gnm_expr_new_binary
			(gnm_expr_copy (expr->binary.value_a),
			 GNM_EXPR_GET_OPER (expr),
			 gnm_expr_copy (expr->binary.value_b));
368

369 370 371 372
	case GNM_EXPR_OP_ANY_UNARY:
		return gnm_expr_new_unary
			(GNM_EXPR_GET_OPER (expr),
			 gnm_expr_copy (expr->unary.value));
373

374 375 376 377
	case GNM_EXPR_OP_FUNCALL: {
		GnmExprConstPtr *argv =
			g_new (GnmExprConstPtr, expr->func.argc);
		int i;
378

379 380
		for (i = 0; i < expr->func.argc; i++)
			argv[i] = gnm_expr_copy (expr->func.argv[i]);
381

382 383 384 385 386
		return gnm_expr_new_funcallv
			(expr->func.func,
			 expr->func.argc,
			 argv);
	}
387

388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438
	case GNM_EXPR_OP_NAME:
		return gnm_expr_new_name
			(expr->name.name,
			 expr->name.optional_scope,
			 expr->name.optional_wb_scope);

	case GNM_EXPR_OP_CONSTANT:
		return gnm_expr_new_constant
			(value_dup (expr->constant.value));

	case GNM_EXPR_OP_CELLREF:
		return gnm_expr_new_cellref (&expr->cellref.ref);

	case GNM_EXPR_OP_ARRAY_CORNER:
		return gnm_expr_new_array_corner
			(expr->array_corner.cols, expr->array_corner.rows,
			 gnm_expr_copy (expr->array_corner.expr));

	case GNM_EXPR_OP_ARRAY_ELEM:
		return gnm_expr_new_array_elem
			(expr->array_elem.x,
			 expr->array_elem.y);

	case GNM_EXPR_OP_SET: {
		GnmExprConstPtr *argv =
			g_new (GnmExprConstPtr, expr->set.argc);
		int i;

		for (i = 0; i < expr->set.argc; i++)
			argv[i] = gnm_expr_copy (expr->set.argv[i]);

		return gnm_expr_new_setv
			(expr->set.argc,
			 argv);
	}

#ifndef DEBUG_SWITCH_ENUM
	default:
		g_assert_not_reached ();
		break;
#endif
	}
}

/*
 * gnm_expr_free:
 */
void
gnm_expr_free (GnmExpr const *expr)
{
	g_return_if_fail (expr != NULL);
Morten Welinder's avatar
Morten Welinder committed
439

440
	switch (GNM_EXPR_GET_OPER (expr)) {
441
	case GNM_EXPR_OP_RANGE_CTOR:
442
	case GNM_EXPR_OP_INTERSECT:
443
	case GNM_EXPR_OP_ANY_BINARY:
444 445
		gnm_expr_free (expr->binary.value_a);
		gnm_expr_free (expr->binary.value_b);
446
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
447
		break;
448

449 450 451 452
	case GNM_EXPR_OP_FUNCALL: {
		int i;

		for (i = 0; i < expr->func.argc; i++)
453
			gnm_expr_free (expr->func.argv[i]);
Morten Welinder's avatar
Morten Welinder committed
454
		g_free (expr->func.argv);
Jody Goldberg's avatar
Jody Goldberg committed
455
		gnm_func_unref (expr->func.func);
456
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
457
		break;
458
	}
459

460
	case GNM_EXPR_OP_NAME:
461
		expr_name_unref (expr->name.name);
462
		CHUNK_FREE (expression_pool_big, (gpointer)expr);
463 464
		break;

465
	case GNM_EXPR_OP_CONSTANT:
Jody Goldberg's avatar
Jody Goldberg committed
466
		value_release ((GnmValue *)expr->constant.value);
467
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
468 469 470
		break;

	case GNM_EXPR_OP_CELLREF:
471
		CHUNK_FREE (expression_pool_big, (gpointer)expr);
472 473
		break;

474
	case GNM_EXPR_OP_ANY_UNARY:
475
		gnm_expr_free (expr->unary.value);
476
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
477
		break;
478

479 480 481
	case GNM_EXPR_OP_ARRAY_CORNER:
		if (expr->array_corner.value)
			value_release (expr->array_corner.value);
482
		gnm_expr_free (expr->array_corner.expr);
483
		CHUNK_FREE (expression_pool_big, (gpointer)expr);
484 485 486
		break;

	case GNM_EXPR_OP_ARRAY_ELEM:
487
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
Jody Goldberg's avatar
Jody Goldberg committed
488
		break;
489

490 491 492 493
	case GNM_EXPR_OP_SET: {
		int i;

		for (i = 0; i < expr->set.argc; i++)
494
			gnm_expr_free (expr->set.argv[i]);
Morten Welinder's avatar
Morten Welinder committed
495
		g_free (expr->set.argv);
496
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
497
		break;
498
	}
499 500

#ifndef DEBUG_SWITCH_ENUM
501
	default:
502
		g_assert_not_reached ();
503
		break;
504
#endif
505
	}
506 507
}

Jody Goldberg's avatar
Jody Goldberg committed
508
/**
509
 * gnm_expr_equal : Returns TRUE if the supplied expressions are exactly the
Jody Goldberg's avatar
Jody Goldberg committed
510
 *   same.  No eval position is used to see if they are effectively the same.
Morten Welinder's avatar
Morten Welinder committed
511
 *   Named expressions must refer the same name, having equivalent names is
Jody Goldberg's avatar
Jody Goldberg committed
512 513
 *   insufficeient.
 */
514
static gboolean
515
gnm_expr_equal (GnmExpr const *a, GnmExpr const *b)
Jody Goldberg's avatar
Jody Goldberg committed
516 517 518 519 520 521 522
{
	if (a == b)
		return TRUE;

	g_return_val_if_fail (a != NULL, FALSE);
	g_return_val_if_fail (b != NULL, FALSE);

523
	if (GNM_EXPR_GET_OPER (a) != GNM_EXPR_GET_OPER (b))
Jody Goldberg's avatar
Jody Goldberg committed
524 525
		return FALSE;

526
	switch (GNM_EXPR_GET_OPER (a)) {
527
	case GNM_EXPR_OP_RANGE_CTOR:
528
	case GNM_EXPR_OP_INTERSECT:
529 530 531
	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
532

533 534
	case GNM_EXPR_OP_ANY_UNARY:
		return gnm_expr_equal (a->unary.value, b->unary.value);
Jody Goldberg's avatar
Jody Goldberg committed
535

536 537 538 539 540 541 542 543 544 545 546 547
	case GNM_EXPR_OP_FUNCALL: {
		int i;

		if (a->func.func != b->func.func ||
		    a->func.argc != b->func.argc)
			return FALSE;

		for (i = 0; i < a->func.argc; i++)
			if (!gnm_expr_equal (a->func.argv[i], b->func.argv[i]))
				return FALSE;
		return TRUE;
	}
Jody Goldberg's avatar
Jody Goldberg committed
548

549
	case GNM_EXPR_OP_NAME:
550 551 552
		return	a->name.name == b->name.name &&
			a->name.optional_scope == b->name.optional_scope &&
			a->name.optional_wb_scope == b->name.optional_wb_scope;
Jody Goldberg's avatar
Jody Goldberg committed
553

554
	case GNM_EXPR_OP_CELLREF:
555
		return gnm_cellref_equal (&a->cellref.ref, &b->cellref.ref);
Jody Goldberg's avatar
Jody Goldberg committed
556

557 558
	case GNM_EXPR_OP_CONSTANT:
		return value_equal (a->constant.value, b->constant.value);
Jody Goldberg's avatar
Jody Goldberg committed
559

560 561 562
	case GNM_EXPR_OP_ARRAY_CORNER: {
		GnmExprArrayCorner const *aa = &a->array_corner;
		GnmExprArrayCorner const *ab = &b->array_corner;
Jody Goldberg's avatar
Jody Goldberg committed
563 564 565

		return	aa->cols == ab->cols &&
			aa->rows == ab->rows &&
566 567 568 569 570 571
			gnm_expr_equal (aa->expr, ab->expr);
	}
	case GNM_EXPR_OP_ARRAY_ELEM: {
		GnmExprArrayElem const *aa = &a->array_elem;
		GnmExprArrayElem const *ab = &b->array_elem;
		return	aa->x == ab->x && aa->y == ab->y;
Jody Goldberg's avatar
Jody Goldberg committed
572 573
	}

574 575 576 577 578 579 580 581 582 583 584
	case GNM_EXPR_OP_SET: {
		int i;

		if (a->set.argc != b->set.argc)
			return FALSE;

		for (i = 0; i < a->set.argc; i++)
			if (!gnm_expr_equal (a->set.argv[i], b->set.argv[i]))
				return FALSE;
		return TRUE;
	}
Jody Goldberg's avatar
Jody Goldberg committed
585 586 587 588 589
	}

	return FALSE;
}

590
static GnmCell *
591 592
array_elem_get_corner (GnmExprArrayElem const *elem,
		       Sheet const *sheet, GnmCellPos const *pos)
593
{
594
	GnmCell *corner = sheet_cell_get (sheet,
595
		pos->col - elem->x, pos->row - elem->y);
596 597 598

	/* Sanity check incase the corner gets removed for some reason */
	g_return_val_if_fail (corner != NULL, NULL);
599
	g_return_val_if_fail (gnm_cell_has_expr (corner), NULL);
600 601
	g_return_val_if_fail (corner->base.texpr != (void *)0xdeadbeef, NULL);
	g_return_val_if_fail (IS_GNM_EXPR_TOP (corner->base.texpr), NULL);
602 603 604 605 606

	return corner;
}

static gboolean
Jody Goldberg's avatar
Jody Goldberg committed
607
gnm_expr_extract_ref (GnmRangeRef *res, GnmExpr const *expr,
Morten Welinder's avatar
Morten Welinder committed
608
		      GnmEvalPos const *pos, GnmExprEvalFlags flags)
609
{
610
	switch (GNM_EXPR_GET_OPER (expr)) {
611 612
	case GNM_EXPR_OP_FUNCALL : {
		gboolean failed = TRUE;
Jody Goldberg's avatar
Jody Goldberg committed
613
		GnmValue *v;
614
		GnmFuncEvalInfo ei;
615

616
		ei.pos = pos;
617
		ei.func_call = &expr->func;
618
		v = function_call_with_exprs (&ei, flags);
619 620

		if (v != NULL) {
Jody Goldberg's avatar
Jody Goldberg committed
621 622
			if (v->type == VALUE_CELLRANGE) {
				*res = v->v_range.cell;
623 624 625 626 627 628 629 630
				failed = FALSE;
			}
			value_release (v);
		}
		return failed;
	}

	case GNM_EXPR_OP_CELLREF :
Jody Goldberg's avatar
Jody Goldberg committed
631 632
		res->a = expr->cellref.ref;
		res->b = expr->cellref.ref;
633 634 635
		return FALSE;

	case GNM_EXPR_OP_CONSTANT: {
Jody Goldberg's avatar
Jody Goldberg committed
636
		GnmValue const *v = expr->constant.value;
Jody Goldberg's avatar
Jody Goldberg committed
637 638
		if (v->type == VALUE_CELLRANGE) {
			*res = v->v_range.cell;
639 640 641 642 643 644
			return FALSE;
		}
		return TRUE;
	}

	case GNM_EXPR_OP_NAME:
645
		if (!expr->name.name->active)
646
			return TRUE;
647 648
		return gnm_expr_extract_ref (res, expr->name.name->texpr->expr,
					     pos, flags);
649 650 651 652 653 654
	default :
		break;
	}
	return TRUE;
}

Jody Goldberg's avatar
Jody Goldberg committed
655 656
static inline GnmValue *
handle_empty (GnmValue *res, GnmExprEvalFlags flags)
657 658 659 660 661
{
	if (res == NULL)
		return (flags & GNM_EXPR_EVAL_PERMIT_EMPTY)
		    ? NULL : value_new_int (0);

662
	if (VALUE_IS_EMPTY (res)) {
663 664 665 666 667 668 669
		value_release (res);
		return (flags & GNM_EXPR_EVAL_PERMIT_EMPTY)
		    ? NULL : value_new_int (0);
	}
	return res;
}

Jody Goldberg's avatar
Jody Goldberg committed
670 671
/**
 * value_intersection :
672
 * @v   : a VALUE_CELLRANGE or VALUE_ARRAY
Morten Welinder's avatar
Morten Welinder committed
673
 * @pos :
Jody Goldberg's avatar
Jody Goldberg committed
674 675 676 677 678 679 680 681 682 683 684 685 686 687 688
 *
 * 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.
 *
 * Always release the value passed in.
 *
 * Return value:
 *     If the intersection succeeded return a duplicate of the value
 *     at the intersection point.  This value needs to be freed.
 *     NULL if there is no intersection
 * Returns the upper left corner of an array.
 **/
Jody Goldberg's avatar
Jody Goldberg committed
689
static GnmValue *
Morten Welinder's avatar
Morten Welinder committed
690
value_intersection (GnmValue *v, GnmEvalPos const *pos)
Jody Goldberg's avatar
Jody Goldberg committed
691
{
Jody Goldberg's avatar
Jody Goldberg committed
692 693
	GnmValue *res = NULL;
	GnmRange r;
Jody Goldberg's avatar
Jody Goldberg committed
694 695 696 697
	Sheet *start_sheet, *end_sheet;
	gboolean found = FALSE;

	if (v->type == VALUE_ARRAY) {
698 699 700
		res = (v->v_array.x == 0 || v->v_array.y == 0)
			? value_new_error_VALUE (NULL)
			: value_dup (v->v_array.vals[0][0]);
Jody Goldberg's avatar
Jody Goldberg committed
701 702 703 704 705
		value_release (v);
		return res;
	}

	/* inverted ranges */
706
	gnm_rangeref_normalize (&v->v_range.cell, pos, &start_sheet, &end_sheet, &r);
Jody Goldberg's avatar
Jody Goldberg committed
707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728
	value_release (v);

	if (start_sheet == end_sheet || end_sheet == NULL) {
		int col = pos->eval.col;
		int row = pos->eval.row;

		if (r.start.row == r.end.row) {
			if (r.start.col <= col && col <= r.end.col) {
				row = r.start.row;
				found = TRUE;
			} else if (r.start.col == r.end.col) {
				col = r.start.col;
				row = r.start.row;
				found = TRUE;
			}
		} else if (r.start.col == r.end.col) {
			if (r.start.row <= row && row <= r.end.row) {
				col = r.start.col;
				found = TRUE;
			}
		}
		if (found) {
729
			GnmCell *cell = sheet_cell_get (
Jody Goldberg's avatar
Jody Goldberg committed
730 731 732 733
				eval_sheet (start_sheet, pos->sheet),
				col, row);
			if (cell == NULL)
				return value_new_empty ();
734
			gnm_cell_eval (cell);
735
			return value_dup (cell->value);
Jody Goldberg's avatar
Jody Goldberg committed
736 737 738
		}
	}

739
	return value_new_error_VALUE (pos);
Jody Goldberg's avatar
Jody Goldberg committed
740
}
741

Jody Goldberg's avatar
Jody Goldberg committed
742
static GnmValue *
743 744
bin_arith (GnmExpr const *expr, GnmEvalPos const *ep,
	   GnmValue const *a, GnmValue const *b)
Jody Goldberg's avatar
Jody Goldberg committed
745
{
746 747 748
	gnm_float const va = value_get_as_float (a);
	gnm_float const vb = value_get_as_float (b);
	gnm_float res;
749

750 751 752 753
	switch (GNM_EXPR_GET_OPER (expr)) {
	case GNM_EXPR_OP_ADD:
		res = va + vb;
		break;
754

755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777
	case GNM_EXPR_OP_SUB:
		res = va - vb;
		break;

	case GNM_EXPR_OP_MULT:
		res = va * vb;
		break;

	case GNM_EXPR_OP_DIV:
		if (vb == 0.0)
			return value_new_error_DIV0 (ep);
		res = va / vb;
		break;

	case GNM_EXPR_OP_EXP:
		if ((va == 0 && vb <= 0) || (va < 0 && vb != (int)vb))
			return value_new_error_NUM (ep);

		res = gnm_pow (va, vb);
		break;

	default:
		g_assert_not_reached ();
778
	}
779

780
	if (gnm_finite (res))
781 782 783
		return value_new_float (res);
	else
		return value_new_error_NUM (ep);
Jody Goldberg's avatar
Jody Goldberg committed
784 785
}

Jody Goldberg's avatar
Jody Goldberg committed
786
static GnmValue *
787
bin_cmp (GnmExprOp op, GnmValDiff comp, GnmEvalPos const *ep)
788 789 790 791 792 793 794 795 796 797 798
{
	if (comp == TYPE_MISMATCH) {
		/* TODO TODO TODO : Make error more informative
		 *    regarding what is comparing to what
		 */
		/* For equality comparisons even errors are ok */
		if (op == GNM_EXPR_OP_EQUAL)
			return value_new_bool (FALSE);
		if (op == GNM_EXPR_OP_NOT_EQUAL)
			return value_new_bool (TRUE);

799
		return value_new_error_VALUE (ep);
800 801 802 803 804 805 806
	}

	switch (op) {
	case GNM_EXPR_OP_EQUAL:     return value_new_bool (comp == IS_EQUAL);
	case GNM_EXPR_OP_GT:	    return value_new_bool (comp == IS_GREATER);
	case GNM_EXPR_OP_LT:	    return value_new_bool (comp == IS_LESS);
	case GNM_EXPR_OP_NOT_EQUAL: return value_new_bool (comp != IS_EQUAL);
807
	case GNM_EXPR_OP_LTE:	    return value_new_bool (comp != IS_GREATER);
808 809 810 811 812 813 814
	case GNM_EXPR_OP_GTE:	    return value_new_bool (comp != IS_LESS);

#ifndef DEBUG_SWITCH_ENUM
	default:
		g_assert_not_reached ();
#endif
	}
815
	return value_new_error (ep, _("Internal type error"));
816 817
}

Jody Goldberg's avatar
Jody Goldberg committed
818
static GnmValue *
819 820
cb_bin_cmp (GnmEvalPos const *ep, GnmValue const *a, GnmValue const *b,
	    GnmExpr const *expr)
821
{
Morten Welinder's avatar
Try!  
Morten Welinder committed
822
	if (a != NULL && VALUE_IS_ERROR (a))
823
		return value_dup (a);
Morten Welinder's avatar
Try!  
Morten Welinder committed
824
	if (b != NULL && VALUE_IS_ERROR (b))
825
		return value_dup (b);
826
	return bin_cmp (GNM_EXPR_GET_OPER (expr), value_compare (a, b, FALSE), ep);
827 828 829 830 831 832 833 834
}

static GnmValue *
cb_bin_arith (GnmEvalPos const *ep, GnmValue const *a, GnmValue const *b,
	      GnmExpr const *expr)
{
	GnmValue *res, *va, *vb;

Morten Welinder's avatar
Try!  
Morten Welinder committed
835
	if (a != NULL && VALUE_IS_ERROR (a))
836
		return value_dup (a);
Morten Welinder's avatar
Try!  
Morten Welinder committed
837
	if (b != NULL && VALUE_IS_ERROR (b))
838
		return value_dup (b);
839
	if (VALUE_IS_EMPTY (a))
840
		a = va = (GnmValue *)value_zero;
841
	else if (VALUE_IS_STRING (a)) {
842
		va = format_match_number (value_peek_string (a), NULL,
843 844 845 846 847 848 849
			workbook_date_conv (ep->sheet->workbook));
		if (va == NULL)
			return value_new_error_VALUE (ep);
	} else if (!VALUE_IS_NUMBER (a))
		return value_new_error_VALUE (ep);
	else
		va = (GnmValue *)a;
850
	if (VALUE_IS_EMPTY (b))
851
		b = vb = (GnmValue *)value_zero;
852
	else if (VALUE_IS_STRING (b)) {
853
		vb = format_match_number (value_peek_string (b), NULL,
854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878
			workbook_date_conv (ep->sheet->workbook));
		if (vb == NULL) {
			if (va != a)
				value_release (va);
			return value_new_error_VALUE (ep);
		}
	} else if (!VALUE_IS_NUMBER (b)) {
		if (va != a)
			value_release (va);
		return value_new_error_VALUE (ep);
	} else
		vb = (GnmValue *)b;

	res = bin_arith (expr, ep, va, vb);
	if (va != a)
		value_release (va);
	if (vb != b)
		value_release (vb);
	return res;
}

static GnmValue *
cb_bin_cat (GnmEvalPos const *ep, GnmValue const *a, GnmValue const *b,
	    GnmExpr const *expr)
{
Morten Welinder's avatar
Try!  
Morten Welinder committed
879
	if (a != NULL && VALUE_IS_ERROR (a))
880
		return value_dup (a);
Morten Welinder's avatar
Try!  
Morten Welinder committed
881
	if (b != NULL && VALUE_IS_ERROR (b))
882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901
		return value_dup (b);
	if (a == NULL) {
		if (b != NULL)
			return value_new_string (value_peek_string (b));
		else
			return value_new_string ("");
	} else if (b == NULL)
		return value_new_string (value_peek_string (a));
	else {
		char *tmp = g_strconcat (value_peek_string (a),
					 value_peek_string (b), NULL);
		return value_new_string_nocopy (tmp);
	}
}

typedef GnmValue *(*BinOpImplicitIteratorFunc) (GnmEvalPos const *ep,
						GnmValue const *a,
						GnmValue const *b,
						gpointer user_data);
typedef struct {
Jody Goldberg's avatar
Jody Goldberg committed
902
	GnmEvalPos const *ep;
903 904 905
	GnmValue *res;
	GnmValue const *a, *b;
	BinOpImplicitIteratorFunc	func;
906 907 908

	/* multiply by 0 in unused dimensions.
	 * this is simpler than lots of conditions
909
	 *	state->use_x.a ? x : 0
910 911 912 913
	 **/
	struct {
		int a, b;
	} x, y;
914 915 916 917
	gpointer	user_data;
} BinOpImplicitIteratorState;

static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
918 919
cb_implicit_iter_a_and_b (GnmValueIter const *v_iter,
			  BinOpImplicitIteratorState const *state)
920
{
Jody Goldberg's avatar
Jody Goldberg committed
921 922 923 924 925 926 927 928 929
	state->res->v_array.vals [v_iter->x][v_iter->y] =
		(*state->func) (v_iter->ep,
			value_area_get_x_y (state->a,
				state->x.a * v_iter->x,
				state->y.a * v_iter->y, v_iter->ep),
			value_area_get_x_y (state->b,
				state->x.b * v_iter->x,
				state->y.b * v_iter->y, v_iter->ep),
			state->user_data);
930 931 932
	return NULL;
}
static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
933 934
cb_implicit_iter_a_to_scalar_b (GnmValueIter const *v_iter,
				BinOpImplicitIteratorState const *state)
935
{
Jody Goldberg's avatar
Jody Goldberg committed
936 937 938
	state->res->v_array.vals [v_iter->x][v_iter->y] =
		(*state->func) (v_iter->ep,
			v_iter->v, state->b, state->user_data);
939 940
	return NULL;
}
941 942 943 944 945 946 947 948 949 950

/* This is only triggered if something returns an array or a range which can
 * only happen if we are in array eval mode. */
static GnmValue *
bin_array_iter_a (GnmEvalPos const *ep,
		  GnmValue *a, GnmValue *b,
		  BinOpImplicitIteratorFunc func,
		  GnmExpr const *expr)
{
	BinOpImplicitIteratorState iter_info;
951

952
	/* a must be a cellrange or array, it can not be NULL */
Jody Goldberg's avatar
Jody Goldberg committed
953
	iter_info.ep   = ep;
954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985
	iter_info.func = func;
	iter_info.user_data = (gpointer) expr;
	iter_info.a = a;
	iter_info.b = b;

	/* matrix to matrix
	 * Use matching positions unless the dimension is singular, in which
	 * case use the zero item
	 * res[x][y] = f(a[singular.a.x ? 0 : x, b[singular.b.x ? 0 : x)
	 *
	 * If both items have non-singular sizes for
	 * the same dimension use the min size (see samples/array.xls) */
	if (b != NULL &&
	    (b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY)) {
		int sa, sb, w = 1, h = 1;

		sa = value_area_get_width  (a, ep);
		sb = value_area_get_width  (b, ep);
		if ((iter_info.x.a = (sa == 1) ? 0 : 1))
			w = sa;
		if ((iter_info.x.b = (sb == 1) ? 0 : 1) && (w > sb || w == 1))
			w = sb;

		sa = value_area_get_height  (a, ep);
		sb = value_area_get_height  (b, ep);
		if ((iter_info.y.a = (sa == 1) ? 0 : 1))
			h = sa;
		if ((iter_info.y.b = (sb == 1) ? 0 : 1) && (h > sb || h == 1))
			h = sb;

		iter_info.res = value_new_array_empty (w, h);
		value_area_foreach (iter_info.res, ep, CELL_ITER_ALL,
Jody Goldberg's avatar
Jody Goldberg committed
986
			(GnmValueIterFunc) cb_implicit_iter_a_and_b, &iter_info);
987 988 989 990 991
	} else {
		iter_info.res = value_new_array_empty (
			value_area_get_width  (a, ep),
			value_area_get_height (a, ep));
		value_area_foreach (a, ep, CELL_ITER_ALL,
Jody Goldberg's avatar
Jody Goldberg committed
992
			(GnmValueIterFunc) cb_implicit_iter_a_to_scalar_b, &iter_info);
993 994 995 996 997 998 999 1000
	}

	value_release (a);
	if (b != NULL)
		value_release (b);
	return iter_info.res;
}

1001
static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
1002 1003
cb_implicit_iter_b_to_scalar_a (GnmValueIter const *v_iter,
				BinOpImplicitIteratorState const *state)
1004
{
Jody Goldberg's avatar
Jody Goldberg committed
1005 1006 1007
	state->res->v_array.vals [v_iter->x][v_iter->y] =
		(*state->func) (v_iter->ep,
			state->a, v_iter->v, state->user_data);
1008 1009 1010
	return NULL;
}
static GnmValue *
1011 1012 1013 1014
bin_array_iter_b (GnmEvalPos const *ep,
		  GnmValue *a, GnmValue *b,
		  BinOpImplicitIteratorFunc func,
		  GnmExpr const *expr)
1015 1016
{
	BinOpImplicitIteratorState iter_info;
1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027

	iter_info.func = func;
	iter_info.user_data = (gpointer) expr;
	iter_info.a = a;
	iter_info.b = b;

	/* b must be a cellrange or array, it can not be NULL */
	iter_info.res = value_new_array_empty (
		value_area_get_width  (b, ep),
		value_area_get_height (b, ep));
	value_area_foreach (b, ep, CELL_ITER_ALL,
Jody Goldberg's avatar
Jody Goldberg committed
1028
		(GnmValueIterFunc) cb_implicit_iter_b_to_scalar_a, &iter_info);
1029 1030
	if (a != NULL)
		value_release (a);
1031 1032
	value_release (b);

1033 1034 1035
	return iter_info.res;
}

1036
static GnmValue *
1037
negate_value (GnmValue const *v)
1038
{
1039 1040 1041 1042
	if (VALUE_IS_NUMBER (v)) {
		GnmValue *tmp = value_new_float (0 - value_get_as_float (v));
		value_set_fmt (tmp, VALUE_FMT (v));
		return tmp;
1043
	} else
1044 1045 1046 1047
		return NULL;
}

static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
1048
cb_iter_unary_neg (GnmValueIter const *v_iter, GnmValue *res)
1049
{
Jody Goldberg's avatar
Jody Goldberg committed
1050
	GnmValue const *v = v_iter->v;
1051 1052 1053 1054
	GnmValue *tmp = NULL;

	if (VALUE_IS_EMPTY (v))
		tmp = value_new_int (0);
Morten Welinder's avatar
Try!  
Morten Welinder committed
1055
	else if (VALUE_IS_ERROR (v))
1056
		tmp = value_dup (v);
1057
	else if (VALUE_IS_STRING (v)) {
Jody Goldberg's avatar
Jody Goldberg committed
1058 1059 1060
		GnmValue *conv = format_match_number (
			value_peek_string (v), NULL,
			workbook_date_conv (v_iter->ep->sheet->workbook));
1061 1062 1063 1064
		if (conv != NULL) {
			tmp = negate_value (conv);
			value_release (conv);
		}
1065 1066
	} else {
		/* BOOL goes here.  */
1067
		tmp = negate_value (v);
1068
	}
1069

Jody Goldberg's avatar
Jody Goldberg committed
1070 1071 1072
	if (NULL == tmp)
		tmp = value_new_error_VALUE (v_iter->ep);
	res->v_array.vals[v_iter->x][v_iter->y] = tmp;
1073 1074 1075 1076
	return NULL;
}

static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
1077
cb_iter_percentage (GnmValueIter const *v_iter, GnmValue *res)
1078
{
Jody Goldberg's avatar
Jody Goldberg committed
1079
	GnmValue const *v = v_iter->v;
1080
	GnmValue *tmp;
1081 1082 1083

	if (VALUE_IS_EMPTY (v))
		tmp = value_new_int (0);
Morten Welinder's avatar
Try!  
Morten Welinder committed
1084
	else if (VALUE_IS_ERROR (v))
1085
		tmp = value_dup (v);
1086 1087
	else {
		GnmValue *conv = NULL;
1088
		if (VALUE_IS_STRING (v)) {
Jody Goldberg's avatar
Jody Goldberg committed
1089 1090 1091
			conv = format_match_number (
				value_peek_string (v), NULL,
				workbook_date_conv (v_iter->ep->sheet->workbook));
1092 1093 1094 1095 1096 1097
			if (conv != NULL)
				v = conv;
		}

		if (VALUE_IS_NUMBER (v)){
			tmp = value_new_float (value_get_as_float (v) / 100);
1098
			value_set_fmt (tmp, go_format_default_percentage ());
1099
		} else
Jody Goldberg's avatar
Jody Goldberg committed
1100
			tmp = value_new_error_VALUE (v_iter->ep);
1101

1102
		if (conv != NULL)
1103
			value_release (conv);
1104 1105
	}

Jody Goldberg's avatar
Jody Goldberg committed
1106
	res->v_array.vals[v_iter->x][v_iter->y] = tmp;
1107
	return NULL;
1108 1109
}