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

Jody Goldberg's avatar
Jody Goldberg committed
44
#include <go-string.h>
45
#include <goffice/goffice.h>
Jody Goldberg's avatar
Jody Goldberg committed
46 47 48
#include <math.h>
#include <string.h>
#include <stdlib.h>
49

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

68 69
/***************************************************************************/

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

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

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

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

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

97
	ans = CHUNK_ALLOC (GnmExprFunction, expression_pool_small);
98

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

105
	return (GnmExpr *)ans;
106
}
107

108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
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
123 124 125 126
GnmExpr const *
gnm_expr_new_funcall1 (GnmFunc *func,
		       GnmExpr const *arg0)
{
127 128 129
	GnmExprConstPtr *argv = g_new (GnmExprConstPtr, 1);
	argv[0] = arg0;
	return gnm_expr_new_funcallv (func, 1, argv);
Morten Welinder's avatar
Morten Welinder committed
130 131 132 133 134 135 136
}

GnmExpr const *
gnm_expr_new_funcall2 (GnmFunc *func,
		       GnmExpr const *arg0,
		       GnmExpr const *arg1)
{
137 138 139 140
	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
141 142 143 144 145 146 147 148
}

GnmExpr const *
gnm_expr_new_funcall3 (GnmFunc *func,
		       GnmExpr const *arg0,
		       GnmExpr const *arg1,
		       GnmExpr const *arg2)
{
149 150 151 152 153
	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
154 155
}

156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
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);
}

171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
GnmExpr const *
gnm_expr_new_funcall5 (GnmFunc *func,
		       GnmExpr const *arg0,
		       GnmExpr const *arg1,
		       GnmExpr const *arg2,
		       GnmExpr const *arg3,
		       GnmExpr const *arg4)
{
	GnmExprConstPtr *argv = g_new (GnmExprConstPtr, 5);
	argv[0] = arg0;
	argv[1] = arg1;
	argv[2] = arg2;
	argv[3] = arg3;
	argv[4] = arg4;
	return gnm_expr_new_funcallv (func, 5, argv);
}

Morten Welinder's avatar
Morten Welinder committed
188

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

191 192
GnmExpr const *
gnm_expr_new_unary  (GnmExprOp op, GnmExpr const *e)
Morten Welinder's avatar
Morten Welinder committed
193
{
194
	GnmExprUnary *ans;
Morten Welinder's avatar
Morten Welinder committed
195

196
	ans = CHUNK_ALLOC (GnmExprUnary, expression_pool_small);
197 198 199
	if (!ans)
		return NULL;

200
	ans->oper = op;
201
	ans->value = e;
202

203
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
204 205
}

Jody Goldberg's avatar
Jody Goldberg committed
206 207
/***************************************************************************/

208 209
GnmExpr const *
gnm_expr_new_binary (GnmExpr const *l, GnmExprOp op, GnmExpr const *r)
Morten Welinder's avatar
Morten Welinder committed
210
{
211
	GnmExprBinary *ans;
Morten Welinder's avatar
Morten Welinder committed
212

213
	ans = CHUNK_ALLOC (GnmExprBinary, expression_pool_small);
214 215
	if (!ans)
		return NULL;
216

217
	ans->oper = op;
218 219
	ans->value_a = l;
	ans->value_b = r;
220

221
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
222 223
}

Jody Goldberg's avatar
Jody Goldberg committed
224 225
/***************************************************************************/

226 227
GnmExpr const *
gnm_expr_new_name (GnmNamedExpr *name,
228
		   Sheet *optional_scope, Workbook *optional_wb_scope)
Morten Welinder's avatar
Morten Welinder committed
229
{
230
	GnmExprName *ans;
Morten Welinder's avatar
Morten Welinder committed
231

232
	ans = CHUNK_ALLOC (GnmExprName, expression_pool_big);
233 234
	if (!ans)
		return NULL;
235

236
	ans->oper = GNM_EXPR_OP_NAME;
237
	ans->name = name;
238
	expr_name_ref (name);
239

240 241 242
	ans->optional_scope = optional_scope;
	ans->optional_wb_scope = optional_wb_scope;

243
	return (GnmExpr *)ans;
Morten Welinder's avatar
Morten Welinder committed
244
}
245

Jody Goldberg's avatar
Jody Goldberg committed
246 247
/***************************************************************************/

248
GnmExpr const *
Jody Goldberg's avatar
Jody Goldberg committed
249
gnm_expr_new_cellref (GnmCellRef const *cr)
250
{
251
	GnmExprCellRef *ans;
252

253
	ans = CHUNK_ALLOC (GnmExprCellRef, expression_pool_big);
254 255
	if (!ans)
		return NULL;
256

257
	ans->oper = GNM_EXPR_OP_CELLREF;
258 259
	ans->ref = *cr;

260
	return (GnmExpr *)ans;
261 262
}

Jody Goldberg's avatar
Jody Goldberg committed
263 264 265
/***************************************************************************/

/**
266
 * gnm_expr_new_array_corner :
Jody Goldberg's avatar
Jody Goldberg committed
267 268 269 270 271 272
 * @cols :
 * @rows :
 * @expr : optionally NULL.
 *
 * Absorb a referernce to @expr if it is non NULL.
 **/
273
static GnmExpr const *
274
gnm_expr_new_array_corner(int cols, int rows, GnmExpr const *expr)
275
{
276
	GnmExprArrayCorner *ans;
277

278
	ans = CHUNK_ALLOC (GnmExprArrayCorner, expression_pool_big);
279 280
	if (ans == NULL)
		return NULL;
281

282
	ans->oper = GNM_EXPR_OP_ARRAY_CORNER;
283 284
	ans->rows = rows;
	ans->cols = cols;
285 286 287 288 289
	ans->value = NULL;
	ans->expr = expr;
	return (GnmExpr *)ans;
}

290
static GnmExpr const *
291 292 293 294
gnm_expr_new_array_elem  (int x, int y)
{
	GnmExprArrayElem *ans;

295
	ans = CHUNK_ALLOC (GnmExprArrayElem, expression_pool_small);
296 297 298
	if (ans == NULL)
		return NULL;

299
	ans->oper = GNM_EXPR_OP_ARRAY_ELEM;
300 301
	ans->x = x;
	ans->y = y;
302
	return (GnmExpr *)ans;
303 304
}

Jody Goldberg's avatar
Jody Goldberg committed
305 306
/***************************************************************************/

307 308
static GnmExpr const *
gnm_expr_new_setv (int argc, GnmExprConstPtr *argv)
Jody Goldberg's avatar
Jody Goldberg committed
309
{
310 311
	GnmExprSet *ans = CHUNK_ALLOC (GnmExprSet, expression_pool_small);

312
	ans->oper = GNM_EXPR_OP_SET;
313 314 315 316
	ans->argc = argc;
	ans->argv = argv;

	return (GnmExpr *)ans;
Jody Goldberg's avatar
Jody Goldberg committed
317 318
}

319 320
GnmExpr const *
gnm_expr_new_set (GnmExprList *set)
321
{
322 323 324
	int i, argc;
	GnmExprConstPtr *argv;
	GnmExprList *set0 = set;
325

326 327 328 329 330
	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);
331

332
	return gnm_expr_new_setv (argc, argv);
333 334
}

Jody Goldberg's avatar
Jody Goldberg committed
335
/***************************************************************************/
336 337 338 339 340 341 342

/**
 * gnm_expr_new_range_ctor:
 * @l: start range
 * @r: end range
 *
 * This function builds a range constructor or something simpler,
Morten Welinder's avatar
Morten Welinder committed
343
 * but equivalent, if the arguments allow it.
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369
 *
 * 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
370

371 372
GnmExpr const *
gnm_expr_copy (GnmExpr const *expr)
373
{
374 375
	g_return_val_if_fail (expr != NULL, NULL);

376 377 378 379 380 381 382 383
	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));
384

385 386 387 388
	case GNM_EXPR_OP_ANY_UNARY:
		return gnm_expr_new_unary
			(GNM_EXPR_GET_OPER (expr),
			 gnm_expr_copy (expr->unary.value));
389

390 391 392 393
	case GNM_EXPR_OP_FUNCALL: {
		GnmExprConstPtr *argv =
			g_new (GnmExprConstPtr, expr->func.argc);
		int i;
394

395 396
		for (i = 0; i < expr->func.argc; i++)
			argv[i] = gnm_expr_copy (expr->func.argv[i]);
397

398 399 400 401 402
		return gnm_expr_new_funcallv
			(expr->func.func,
			 expr->func.argc,
			 argv);
	}
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 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
	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
455

456
	switch (GNM_EXPR_GET_OPER (expr)) {
457
	case GNM_EXPR_OP_RANGE_CTOR:
458
	case GNM_EXPR_OP_INTERSECT:
459
	case GNM_EXPR_OP_ANY_BINARY:
460 461
		gnm_expr_free (expr->binary.value_a);
		gnm_expr_free (expr->binary.value_b);
462
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
463
		break;
464

465 466 467 468
	case GNM_EXPR_OP_FUNCALL: {
		int i;

		for (i = 0; i < expr->func.argc; i++)
469
			gnm_expr_free (expr->func.argv[i]);
Morten Welinder's avatar
Morten Welinder committed
470
		g_free (expr->func.argv);
Jody Goldberg's avatar
Jody Goldberg committed
471
		gnm_func_unref (expr->func.func);
472
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
473
		break;
474
	}
475

476
	case GNM_EXPR_OP_NAME:
477
		expr_name_unref (expr->name.name);
478
		CHUNK_FREE (expression_pool_big, (gpointer)expr);
479 480
		break;

481
	case GNM_EXPR_OP_CONSTANT:
Jody Goldberg's avatar
Jody Goldberg committed
482
		value_release ((GnmValue *)expr->constant.value);
483
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
484 485 486
		break;

	case GNM_EXPR_OP_CELLREF:
487
		CHUNK_FREE (expression_pool_big, (gpointer)expr);
488 489
		break;

490
	case GNM_EXPR_OP_ANY_UNARY:
491
		gnm_expr_free (expr->unary.value);
492
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
493
		break;
494

495 496 497
	case GNM_EXPR_OP_ARRAY_CORNER:
		if (expr->array_corner.value)
			value_release (expr->array_corner.value);
498
		gnm_expr_free (expr->array_corner.expr);
499
		CHUNK_FREE (expression_pool_big, (gpointer)expr);
500 501 502
		break;

	case GNM_EXPR_OP_ARRAY_ELEM:
503
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
Jody Goldberg's avatar
Jody Goldberg committed
504
		break;
505

506 507 508 509
	case GNM_EXPR_OP_SET: {
		int i;

		for (i = 0; i < expr->set.argc; i++)
510
			gnm_expr_free (expr->set.argv[i]);
Morten Welinder's avatar
Morten Welinder committed
511
		g_free (expr->set.argv);
512
		CHUNK_FREE (expression_pool_small, (gpointer)expr);
513
		break;
514
	}
515 516

#ifndef DEBUG_SWITCH_ENUM
517
	default:
518
		g_assert_not_reached ();
519
		break;
520
#endif
521
	}
522 523
}

Jody Goldberg's avatar
Jody Goldberg committed
524
/**
525
 * gnm_expr_equal : Returns TRUE if the supplied expressions are exactly the
Jody Goldberg's avatar
Jody Goldberg committed
526
 *   same.  No eval position is used to see if they are effectively the same.
Morten Welinder's avatar
Morten Welinder committed
527
 *   Named expressions must refer the same name, having equivalent names is
Jody Goldberg's avatar
Jody Goldberg committed
528 529
 *   insufficeient.
 */
530
static gboolean
531
gnm_expr_equal (GnmExpr const *a, GnmExpr const *b)
Jody Goldberg's avatar
Jody Goldberg committed
532 533 534 535 536 537 538
{
	if (a == b)
		return TRUE;

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

539
	if (GNM_EXPR_GET_OPER (a) != GNM_EXPR_GET_OPER (b))
Jody Goldberg's avatar
Jody Goldberg committed
540 541
		return FALSE;

542
	switch (GNM_EXPR_GET_OPER (a)) {
543
	case GNM_EXPR_OP_RANGE_CTOR:
544
	case GNM_EXPR_OP_INTERSECT:
545 546 547
	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
548

549 550
	case GNM_EXPR_OP_ANY_UNARY:
		return gnm_expr_equal (a->unary.value, b->unary.value);
Jody Goldberg's avatar
Jody Goldberg committed
551

552 553 554 555 556 557 558 559 560 561 562 563
	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
564

565
	case GNM_EXPR_OP_NAME:
566 567 568
		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
569

570
	case GNM_EXPR_OP_CELLREF:
571
		return gnm_cellref_equal (&a->cellref.ref, &b->cellref.ref);
Jody Goldberg's avatar
Jody Goldberg committed
572

573 574
	case GNM_EXPR_OP_CONSTANT:
		return value_equal (a->constant.value, b->constant.value);
Jody Goldberg's avatar
Jody Goldberg committed
575

576 577 578
	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
579 580 581

		return	aa->cols == ab->cols &&
			aa->rows == ab->rows &&
582 583 584 585 586 587
			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
588 589
	}

590 591 592 593 594 595 596 597 598 599 600
	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
601 602 603 604 605
	}

	return FALSE;
}

606
static GnmCell *
607 608
array_elem_get_corner (GnmExprArrayElem const *elem,
		       Sheet const *sheet, GnmCellPos const *pos)
609
{
610
	GnmCell *corner = sheet_cell_get (sheet,
611
		pos->col - elem->x, pos->row - elem->y);
612 613 614

	/* Sanity check incase the corner gets removed for some reason */
	g_return_val_if_fail (corner != NULL, NULL);
615
	g_return_val_if_fail (gnm_cell_has_expr (corner), NULL);
616 617
	g_return_val_if_fail (corner->base.texpr != (void *)0xdeadbeef, NULL);
	g_return_val_if_fail (IS_GNM_EXPR_TOP (corner->base.texpr), NULL);
618 619 620 621 622

	return corner;
}

static gboolean
Jody Goldberg's avatar
Jody Goldberg committed
623
gnm_expr_extract_ref (GnmRangeRef *res, GnmExpr const *expr,
Morten Welinder's avatar
Morten Welinder committed
624
		      GnmEvalPos const *pos, GnmExprEvalFlags flags)
625
{
626
	switch (GNM_EXPR_GET_OPER (expr)) {
627 628
	case GNM_EXPR_OP_FUNCALL : {
		gboolean failed = TRUE;
Jody Goldberg's avatar
Jody Goldberg committed
629
		GnmValue *v;
630
		GnmFuncEvalInfo ei;
631

632
		ei.pos = pos;
633
		ei.func_call = &expr->func;
634
		v = function_call_with_exprs (&ei, flags);
635 636

		if (v != NULL) {
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 645 646
				failed = FALSE;
			}
			value_release (v);
		}
		return failed;
	}

	case GNM_EXPR_OP_CELLREF :
Jody Goldberg's avatar
Jody Goldberg committed
647 648
		res->a = expr->cellref.ref;
		res->b = expr->cellref.ref;
649 650 651
		return FALSE;

	case GNM_EXPR_OP_CONSTANT: {
Jody Goldberg's avatar
Jody Goldberg committed
652
		GnmValue const *v = expr->constant.value;
Jody Goldberg's avatar
Jody Goldberg committed
653 654
		if (v->type == VALUE_CELLRANGE) {
			*res = v->v_range.cell;
655 656 657 658 659 660
			return FALSE;
		}
		return TRUE;
	}

	case GNM_EXPR_OP_NAME:
661
		if (!expr->name.name->active)
662
			return TRUE;
663 664
		return gnm_expr_extract_ref (res, expr->name.name->texpr->expr,
					     pos, flags);
665 666 667 668 669 670
	default :
		break;
	}
	return TRUE;
}

Jody Goldberg's avatar
Jody Goldberg committed
671 672
static inline GnmValue *
handle_empty (GnmValue *res, GnmExprEvalFlags flags)
673 674 675 676 677
{
	if (res == NULL)
		return (flags & GNM_EXPR_EVAL_PERMIT_EMPTY)
		    ? NULL : value_new_int (0);

678
	if (VALUE_IS_EMPTY (res)) {
679 680 681 682 683 684 685
		value_release (res);
		return (flags & GNM_EXPR_EVAL_PERMIT_EMPTY)
		    ? NULL : value_new_int (0);
	}
	return res;
}

Jody Goldberg's avatar
Jody Goldberg committed
686 687
/**
 * value_intersection :
688
 * @v   : a VALUE_CELLRANGE or VALUE_ARRAY
Morten Welinder's avatar
Morten Welinder committed
689
 * @pos :
Jody Goldberg's avatar
Jody Goldberg committed
690 691 692 693 694 695 696 697 698 699 700 701 702 703 704
 *
 * 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
705
static GnmValue *
Morten Welinder's avatar
Morten Welinder committed
706
value_intersection (GnmValue *v, GnmEvalPos const *pos)
Jody Goldberg's avatar
Jody Goldberg committed
707
{
Jody Goldberg's avatar
Jody Goldberg committed
708 709
	GnmValue *res = NULL;
	GnmRange r;
Jody Goldberg's avatar
Jody Goldberg committed
710 711 712 713
	Sheet *start_sheet, *end_sheet;
	gboolean found = FALSE;

	if (v->type == VALUE_ARRAY) {
714 715 716
		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
717 718 719 720 721
		value_release (v);
		return res;
	}

	/* inverted ranges */
722
	gnm_rangeref_normalize (&v->v_range.cell, pos, &start_sheet, &end_sheet, &r);
Jody Goldberg's avatar
Jody Goldberg committed
723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744
	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) {
745
			GnmCell *cell = sheet_cell_get (
Jody Goldberg's avatar
Jody Goldberg committed
746 747 748 749
				eval_sheet (start_sheet, pos->sheet),
				col, row);
			if (cell == NULL)
				return value_new_empty ();
750
			gnm_cell_eval (cell);
751
			return value_dup (cell->value);
Jody Goldberg's avatar
Jody Goldberg committed
752 753 754
		}
	}

755
	return value_new_error_VALUE (pos);
Jody Goldberg's avatar
Jody Goldberg committed
756
}
757

Jody Goldberg's avatar
Jody Goldberg committed
758
static GnmValue *
759 760
bin_arith (GnmExpr const *expr, GnmEvalPos const *ep,
	   GnmValue const *a, GnmValue const *b)
Jody Goldberg's avatar
Jody Goldberg committed
761
{
762 763 764
	gnm_float const va = value_get_as_float (a);
	gnm_float const vb = value_get_as_float (b);
	gnm_float res;
765

766 767 768 769
	switch (GNM_EXPR_GET_OPER (expr)) {
	case GNM_EXPR_OP_ADD:
		res = va + vb;
		break;
770

771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793
	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 ();
794
	}
795

796
	if (gnm_finite (res))
797 798 799
		return value_new_float (res);
	else
		return value_new_error_NUM (ep);
Jody Goldberg's avatar
Jody Goldberg committed
800 801
}

Jody Goldberg's avatar
Jody Goldberg committed
802
static GnmValue *
803
bin_cmp (GnmExprOp op, GnmValDiff comp, GnmEvalPos const *ep)
804 805 806 807 808 809 810 811 812 813 814
{
	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);

815
		return value_new_error_VALUE (ep);
816 817 818 819 820 821 822
	}

	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);
823
	case GNM_EXPR_OP_LTE:	    return value_new_bool (comp != IS_GREATER);
824 825 826 827 828 829 830
	case GNM_EXPR_OP_GTE:	    return value_new_bool (comp != IS_LESS);

#ifndef DEBUG_SWITCH_ENUM
	default:
		g_assert_not_reached ();
#endif
	}
831
	return value_new_error (ep, _("Internal type error"));
832 833
}

Jody Goldberg's avatar
Jody Goldberg committed
834
static GnmValue *
835 836
cb_bin_cmp (GnmEvalPos const *ep, GnmValue const *a, GnmValue const *b,
	    GnmExpr const *expr)
837
{
Morten Welinder's avatar
Try!  
Morten Welinder committed
838
	if (a != NULL && VALUE_IS_ERROR (a))
839
		return value_dup (a);
Morten Welinder's avatar
Try!  
Morten Welinder committed
840
	if (b != NULL && VALUE_IS_ERROR (b))
841
		return value_dup (b);
842
	return bin_cmp (GNM_EXPR_GET_OPER (expr), value_compare (a, b, FALSE), ep);
843 844 845 846 847 848 849 850
}

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
851
	if (a != NULL && VALUE_IS_ERROR (a))
852
		return value_dup (a);
Morten Welinder's avatar
Try!  
Morten Welinder committed
853
	if (b != NULL && VALUE_IS_ERROR (b))
854
		return value_dup (b);
855
	if (VALUE_IS_EMPTY (a))
856
		a = va = (GnmValue *)value_zero;
857
	else if (VALUE_IS_STRING (a)) {
858
		va = format_match_number (value_peek_string (a), NULL,
859 860 861 862 863 864 865
			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;
866
	if (VALUE_IS_EMPTY (b))
867
		b = vb = (GnmValue *)value_zero;
868
	else if (VALUE_IS_STRING (b)) {
869
		vb = format_match_number (value_peek_string (b), NULL,
870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894
			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
895
	if (a != NULL && VALUE_IS_ERROR (a))
896
		return value_dup (a);
Morten Welinder's avatar
Try!  
Morten Welinder committed
897
	if (b != NULL && VALUE_IS_ERROR (b))
898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917
		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
918
	GnmEvalPos const *ep;
919 920 921
	GnmValue *res;
	GnmValue const *a, *b;
	BinOpImplicitIteratorFunc	func;
922 923 924

	/* multiply by 0 in unused dimensions.
	 * this is simpler than lots of conditions
925
	 *	state->use_x.a ? x : 0
926 927 928 929
	 **/
	struct {
		int a, b;
	} x, y;
930 931 932 933
	gpointer	user_data;
} BinOpImplicitIteratorState;

static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
934 935
cb_implicit_iter_a_and_b (GnmValueIter const *v_iter,
			  BinOpImplicitIteratorState const *state)
936
{
Jody Goldberg's avatar
Jody Goldberg committed
937 938 939 940 941 942 943 944 945
	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);
946 947 948
	return NULL;
}
static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
949 950
cb_implicit_iter_a_to_scalar_b (GnmValueIter const *v_iter,
				BinOpImplicitIteratorState const *state)
951
{
Jody Goldberg's avatar
Jody Goldberg committed
952 953 954
	state->res->v_array.vals [v_iter->x][v_iter->y] =
		(*state->func) (v_iter->ep,
			v_iter->v, state->b, state->user_data);
955 956
	return NULL;
}
957 958 959 960 961 962 963 964 965 966

/* 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;
967

968
	/* a must be a cellrange or array, it can not be NULL */
Jody Goldberg's avatar
Jody Goldberg committed
969
	iter_info.ep   = ep;
970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001
	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
1002
			(GnmValueIterFunc) cb_implicit_iter_a_and_b, &iter_info);
1003 1004 1005 1006 1007
	} 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
1008
			(GnmValueIterFunc) cb_implicit_iter_a_to_scalar_b, &iter_info);
1009 1010 1011 1012 1013 1014 1015 1016
	}

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

1017
static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
1018 1019
cb_implicit_iter_b_to_scalar_a (GnmValueIter const *v_iter,
				BinOpImplicitIteratorState const *state)
1020
{
Jody Goldberg's avatar
Jody Goldberg committed
1021 1022 1023
	state->res->v_array.vals [v_iter->x][v_iter->y] =
		(*state->func) (v_iter->ep,
			state->a, v_iter->v, state->user_data);
1024 1025 1026
	return NULL;
}
static GnmValue *
1027 1028 1029 1030
bin_array_iter_b (GnmEvalPos const *ep,
		  GnmValue *a, GnmValue *b,
		  BinOpImplicitIteratorFunc func,
		  GnmExpr const *expr)
1031 1032
{
	BinOpImplicitIteratorState iter_info;
1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043

	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
1044
		(GnmValueIterFunc) cb_implicit_iter_b_to_scalar_a, &iter_info);
1045 1046
	if (a != NULL)
		value_release (a);
1047 1048
	value_release (b);

1049 1050 1051
	return iter_info.res;
}

1052
static GnmValue *
1053
negate_value (GnmValue const *v)
1054
{
1055 1056 1057 1058
	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;
1059
	} else
1060 1061 1062 1063
		return NULL;
}

static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
1064
cb_iter_unary_neg (GnmValueIter const *v_iter, GnmValue *res)
1065
{
Jody Goldberg's avatar
Jody Goldberg committed
1066
	GnmValue const *v = v_iter->v;
1067 1068 1069 1070
	GnmValue *tmp = NULL;

	if (VALUE_IS_EMPTY (v))
		tmp = value_new_int (0);
Morten Welinder's avatar
Try!  
Morten Welinder committed
1071
	else if (VALUE_IS_ERROR (v))
1072
		tmp = value_dup (v);
1073
	else if (VALUE_IS_STRING (v)) {
Jody Goldberg's avatar
Jody Goldberg committed
1074 1075 1076
		GnmValue *conv = format_match_number (
			value_peek_string (v), NULL,
			workbook_date_conv (v_iter->ep->sheet->workbook));
1077 1078 1079 1080
		if (conv != NULL) {
			tmp = negate_value (conv);
			value_release (conv);
		}
1081 1082
	} else {
		/* BOOL goes here.  */
1083
		tmp = negate_value (v);
1084
	}
1085

Jody Goldberg's avatar
Jody Goldberg committed
1086 1087 1088
	if (NULL == tmp)
		tmp = value_new_error_VALUE (v_iter->ep);
	res->v_array.vals[v_iter->x][v_iter->y] = tmp;
1089 1090 1091 1092
	return NULL;
}

static GnmValue *
Jody Goldberg's avatar
Jody Goldberg committed
1093
cb_iter_percentage (GnmValueIter const *v_iter, GnmValue *res)
1094
{
Jody Goldberg's avatar
Jody Goldberg committed
1095
	GnmValue const *v = v_iter->v;
1096
	GnmValue *tmp;
1097 1098 1099

	if (VALUE_IS_EMPTY (v))
		tmp = value_new_int (0);
Morten Welinder's avatar
Try!  
Morten Welinder committed
1100
	else if (VALUE_IS_ERROR (v))
1101
		tmp = value_dup (v);
1102 1103
	else {
		GnmValue *conv = NULL;
1104
		if (VALUE_IS_STRING (v)) {
Jody Goldberg's avatar
Jody Goldberg committed
1105 1106 1107
			conv = format_match_number (
				value_peek_string (v), NULL,
				workbook_date_conv (v_iter->ep->sheet->workbook));
1108 1109 1110 1111 1112 1113
			if (conv != NULL)
				v = conv;
		}

		if (VALUE_IS_NUMBER (v)){
			tmp = value_new_float (value_get_as_float (v) / 100);
1114
			value_set_fmt (tmp, go_format_default_percentage ());
1115
		} else
Jody Goldberg's avatar
Jody Goldberg committed
1116
			tmp = value_new_error_VALUE (v_iter->ep);
1117

1118
		if (conv != NULL)
1119
			value_release (conv);