Commit d1bcb69c authored by Jody Goldberg's avatar Jody Goldberg Committed by Jody Goldberg

take a CellPos. (applix_read_cells) : tidy a smidge. (applix_read_impl) :


2002-06-21  Jody Goldberg <jody@gnome.org>

	* applix-read.c (applix_parse_cellref) : take a CellPos.
	(applix_read_cells) : tidy a smidge.
	(applix_read_impl) : start to support named ranges.

2002-06-22  Jody Goldberg <jody@gnome.org>

	* ms-formula-read.c (ms_excel_parse_formula) : enable mem_func
	  support.
	(binary_ops) : use range_ctor for RANGE.

2002-06-22  Jody Goldberg <jody@gnome.org>

	* src/expr.h : support constructed ranges.
	* src/parser.y (parser_sheet_by_name) : ditto.
	* src/expr-name.c (name_refer_circular) : ditto.

	* src/expr.c (do_gnm_expr_unref) : support range_ctor and reorder to
	  produce a better jump table.
	(gnm_expr_equal) : ditto.
	(do_expr_as_string) : ditto.
	(gnm_expr_rewrite) : ditto.
	(ets_hash) : ditto.
	(ets_equal) : ditto.
	(expr_tree_sharer_share) : ditto.
	(expr_eval_real) : ditto and use gnm_expr_extract_ref.
	(gnm_expr_extract_ref) : new.
parent d34c075f
......@@ -10,11 +10,17 @@ Release Critical
- We need to somehow add --export-dynamic to the gnumeric link line, or else
plugins won't load on Solaris/gcc. (This might just be my bastard libtool.)
- 3D reference fixes on sheet deletion
- Re-enable autoexpressions
- Dependencies for constructed ranges
- Figure out why the cursor is not on the edit pos when loading an xls fromthe
cmd line.
- Finish support for named ranges in applix.
- mps importer fails to import the mps sample files afiro.mps and blend.mps
1.2 Targets
-----------
- xls export of constructed ranges
- load/save of external references
- String functions need to be UTF8ed: CHAR, CODE, SUBSTITUTE, SEARCH.
- Search/Replace needs to be UTF8ed.
......
2002-06-22 Jody Goldberg <jody@gnome.org>
* src/expr.h : support constructed ranges.
* src/parser.y (parser_sheet_by_name) : ditto.
* src/expr-name.c (name_refer_circular) : ditto.
* src/expr.c (do_gnm_expr_unref) : support range_ctor and reorder to
produce a better jump table.
(gnm_expr_equal) : ditto.
(do_expr_as_string) : ditto.
(gnm_expr_rewrite) : ditto.
(ets_hash) : ditto.
(ets_equal) : ditto.
(expr_tree_sharer_share) : ditto.
(expr_eval_real) : ditto and use gnm_expr_extract_ref.
(gnm_expr_extract_ref) : new.
2002-06-21 Jody Goldberg <jody@gnome.org>
* src/workbook-view.c (workbook_view_new) : add views of all existing
......
......@@ -17,9 +17,10 @@ Jody:
* Fix goto dialog's handling of invalid addresses.
* forward port missing patched from 1.0
* Finally add SheetView
* move animated cursor selection to sheetview
* handle enabling paste special on an application level
* move selection to sheetview
* Move animated cursor selection to sheetview
* Handle enabling paste special on an application level
* Move selection to SheetView
* Parse and evaluate constructed references, no depends yet.
Jukka:
* More solver enhancements:
......
2002-06-22 Jody Goldberg <jody@gnome.org>
* src/expr.h : support constructed ranges.
* src/parser.y (parser_sheet_by_name) : ditto.
* src/expr-name.c (name_refer_circular) : ditto.
* src/expr.c (do_gnm_expr_unref) : support range_ctor and reorder to
produce a better jump table.
(gnm_expr_equal) : ditto.
(do_expr_as_string) : ditto.
(gnm_expr_rewrite) : ditto.
(ets_hash) : ditto.
(ets_equal) : ditto.
(expr_tree_sharer_share) : ditto.
(expr_eval_real) : ditto and use gnm_expr_extract_ref.
(gnm_expr_extract_ref) : new.
2002-06-21 Jody Goldberg <jody@gnome.org>
* src/workbook-view.c (workbook_view_new) : add views of all existing
......
2002-06-22 Jody Goldberg <jody@gnome.org>
* src/expr.h : support constructed ranges.
* src/parser.y (parser_sheet_by_name) : ditto.
* src/expr-name.c (name_refer_circular) : ditto.
* src/expr.c (do_gnm_expr_unref) : support range_ctor and reorder to
produce a better jump table.
(gnm_expr_equal) : ditto.
(do_expr_as_string) : ditto.
(gnm_expr_rewrite) : ditto.
(ets_hash) : ditto.
(ets_equal) : ditto.
(expr_tree_sharer_share) : ditto.
(expr_eval_real) : ditto and use gnm_expr_extract_ref.
(gnm_expr_extract_ref) : new.
2002-06-21 Jody Goldberg <jody@gnome.org>
* src/workbook-view.c (workbook_view_new) : add views of all existing
......
......@@ -2,7 +2,7 @@
* applix-read.c (applix_parse_cellref) : take a CellPos.
(applix_read_cells) : tidy a smidge.
(applix_read_impl) :
(applix_read_impl) : start to support named ranges.
2002-06-20 Jody Goldberg <jody@gnome.org>
......
......@@ -1113,27 +1113,64 @@ applix_read_row_list (ApplixReadState *state, unsigned char *ptr)
return 0;
}
static int
static gboolean
applix_read_sheet_table (ApplixReadState *state)
{
unsigned char *ptr;
while (NULL != (ptr = applix_get_line (state)))
if (!a_strncmp (ptr, "END SHEETS TABLE"))
return 0;
return FALSE;
#warning TODO
return 1;
return TRUE;
}
static int
static gboolean
applix_read_header_footer (ApplixReadState *state)
{
unsigned char *ptr;
while (NULL != (ptr = applix_get_line (state)))
if (!a_strncmp (ptr, "Headers And Footers End"))
return 0;
return 1;
return FALSE;
return TRUE;
}
static gboolean
applix_read_relative_name (ApplixReadState *state, char *buffer)
{
char *end;
/* .ABCDe. Coordinate: A:B2..A:C4 */
/* Spec guarantees that there are no dots in the name */
buffer = strchr (buffer, '.');
if (buffer == NULL)
return TRUE;
end = strchr (++buffer, '.');
if (end == NULL)
return TRUE;
*end = '\0';
#if 0
GnmExpr *expr = gnm_expr_parse_str (expr_string+1,
parse_pos_init_cell (&pos, cell),
GNM_EXPR_PARSE_USE_APPLIX_REFERENCE_CONVENTIONS |
GNM_EXPR_PARSE_CREATE_PLACEHOLDER_FOR_UNKNOWN_FUNC,
&perr);
#endif
puts (buffer);
return FALSE;
}
static gboolean
applix_read_absolute_name (ApplixReadState *state, char *buffer)
{
/* .abcdE. tCol:0 tRow:0 tSheet:0 bCol:1 bRow:2 bSheet: 0 tColAbs:0 tRowAbs:0 tSheetAbs:1 bColAbs:0 bRowAbs:0 bSheetAbs:1 */
/* Spec guarantees that there are no dots in the name */
puts (buffer);
return FALSE;
}
#define ABS_NAMED_RANGE "Named Range, Name:"
#define REL_NAMED_RANGE "Relative Named Range, Name:"
static int
applix_read_impl (ApplixReadState *state)
{
......@@ -1235,6 +1272,12 @@ applix_read_impl (ApplixReadState *state)
} else if (!a_strncmp (buffer, "SHEETS TABLE")) {
if (applix_read_sheet_table (state))
return applix_parse_error (state, "sheet table");
} else if (!a_strncmp (buffer, ABS_NAMED_RANGE)) {
if (applix_read_absolute_name (state, buffer + sizeof (ABS_NAMED_RANGE)))
return applix_parse_error (state, "Absolute named range");
} else if (!a_strncmp (buffer, REL_NAMED_RANGE)) {
if (applix_read_relative_name (state, buffer + sizeof (REL_NAMED_RANGE)))
return applix_parse_error (state, "Absolute named range");
} else if (!a_strncmp (buffer, "Row List")) {
if (applix_read_row_list (state, buffer + sizeof ("Row List")))
return applix_parse_error (state, "row list");
......
2002-06-22 Jody Goldberg <jody@gnome.org>
* ms-formula-read.c (ms_excel_parse_formula) : enable mem_func
support.
(binary_ops) : use range_ctor for RANGE.
2002-06-20 Jody Goldberg <jody@gnome.org>
* ms-excel-read.c (ms_excel_workbook_new) : store the workbookview.
......
......@@ -697,7 +697,7 @@ static GnmExprOp const binary_ops [] = {
/* FIXME: These need implementing ... */
GNM_EXPR_OP_ADD, /* 0x0f, ptgIsect : Intersection */
GNM_EXPR_OP_ADD, /* 0x10, ptgUnion : Union */
GNM_EXPR_OP_ADD, /* 0x11, ptgRange : Range */
GNM_EXPR_OP_RANGE_CTOR /* 0x11, ptgRange : Range */
};
static GnmExprOp const unary_ops [] = {
......@@ -1218,12 +1218,10 @@ ms_excel_parse_formula (ExcelWorkbook const *ewb,
}
break;
#if 0
case FORMULA_PTG_MEM_FUNC:
/* Can I just ignore this ? */
ptg_length = 2 + GSF_LE_GET_GUINT16 (cur);
ptg_length = 2; /* + GSF_LE_GET_GUINT16 (cur); */
break;
#endif
case FORMULA_PTG_REF_ERR:
ptg_length = (ver >= MS_BIFF_V8) ? 4 : 3;
......
2002-06-22 Jody Goldberg <jody@gnome.org>
* functions.c (gnumeric_offset) : no need to special case 1x1 results.
but add some clipping for the 2nd
2002-05-29 Jody Goldberg <jody@gnome.org>
* Release 1.1.4
......
......@@ -976,17 +976,11 @@ gnumeric_offset (FunctionEvalInfo *ei, Value **args)
else if (a.row >= SHEET_MAX_ROWS || a.col >= SHEET_MAX_COLS)
return value_new_error (ei->pos, gnumeric_err_REF);
/* Special case of a single cell */
if (width == 1 && height == 1) {
/* FIXME FIXME : do we need to check for recalc here ?? */
Cell const * c =
sheet_cell_fetch (eval_sheet (a.sheet, ei->pos->sheet),
a.col, a.row);
return value_duplicate (c->value);
}
b.row += width-1;
b.col += height-1;
if (b.row >= SHEET_MAX_ROWS || b.col >= SHEET_MAX_COLS)
return value_new_error (ei->pos, gnumeric_err_REF);
return value_new_cellrange (&a, &b, ei->pos->eval.col, ei->pos->eval.row);
}
......
......@@ -151,8 +151,6 @@ excel_gb_range_select (GBRunEvalContext *ec,
range->range.end.col,
range->range.end.row);
sheet_selection_redraw (range->sheet);
return gb_value_new_empty ();
}
......
......@@ -777,6 +777,8 @@ link_expr_dep (Dependent *dep, CellPos const *pos, GnmExpr const *tree)
res |= link_expr_dep (dep, pos, l->data);
return res;
}
case GNM_EXPR_OP_RANGE_CTOR:
return DEPENDENT_NO_FLAG; /* handled at run time */
default:
g_warning ("Unknown Operation type, dependencies lost");
......
......@@ -78,14 +78,14 @@ union _GnmExpr {
int ref_count;
} any;
GnmExprConstant constant;
GnmExprFunction func;
GnmExprUnary unary;
GnmExprBinary binary;
GnmExprName name;
GnmExprCellRef cellref;
GnmExprArray array;
GnmExprSet set;
GnmExprConstant constant;
GnmExprFunction func;
GnmExprUnary unary;
GnmExprBinary binary;
GnmExprName name;
GnmExprCellRef cellref;
GnmExprArray array;
GnmExprSet set;
};
#define gnm_expr_constant_init(expr, val) \
......
......@@ -204,6 +204,7 @@ name_refer_circular (char const *name, GnmExpr const *expr)
g_return_val_if_fail (expr != NULL, TRUE);
switch (expr->any.oper) {
case GNM_EXPR_OP_RANGE_CTOR:
case GNM_EXPR_OP_ANY_BINARY:
return (name_refer_circular (name, expr->binary.value_a) ||
name_refer_circular (name, expr->binary.value_b));
......
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* expr.c: Expression evaluation in Gnumeric
* expr.c : Expression evaluation in Gnumeric
*
* Author:
* Miguel de Icaza (miguel@gnu.org).
* Copyright (C) 2001-2002 Jody Goldberg (jody@gnome.org)
*
* 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
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include <gnumeric-config.h>
#include "gnumeric.h"
......@@ -301,24 +314,6 @@ gnm_expr_new_set (GnmExprList *set)
return (GnmExpr *)ans;
}
static Cell *
expr_array_corner (GnmExpr const *expr,
Sheet const *sheet, CellPos const *pos)
{
Cell *corner = sheet_cell_get (sheet,
pos->col - expr->array.x, pos->row - expr->array.y);
/* Sanity check incase the corner gets removed for some reason */
g_return_val_if_fail (corner != NULL, NULL);
g_return_val_if_fail (cell_has_expr (corner), NULL);
g_return_val_if_fail (corner->base.expression != (void *)0xdeadbeef, NULL);
g_return_val_if_fail (corner->base.expression->any.oper == GNM_EXPR_OP_ARRAY, NULL);
g_return_val_if_fail (corner->base.expression->array.x == 0, NULL);
g_return_val_if_fail (corner->base.expression->array.y == 0, NULL);
return corner;
}
/***************************************************************************/
/**
......@@ -341,11 +336,10 @@ do_gnm_expr_unref (GnmExpr const *expr)
return;
switch (expr->any.oper) {
case GNM_EXPR_OP_CELLREF:
break;
case GNM_EXPR_OP_CONSTANT:
value_release ((Value *)expr->constant.value);
case GNM_EXPR_OP_RANGE_CTOR:
case GNM_EXPR_OP_ANY_BINARY:
do_gnm_expr_unref (expr->binary.value_a);
do_gnm_expr_unref (expr->binary.value_b);
break;
case GNM_EXPR_OP_FUNCALL:
......@@ -357,25 +351,28 @@ do_gnm_expr_unref (GnmExpr const *expr)
expr_name_unref (expr->name.name);
break;
case GNM_EXPR_OP_ANY_BINARY:
do_gnm_expr_unref (expr->binary.value_a);
do_gnm_expr_unref (expr->binary.value_b);
case GNM_EXPR_OP_CONSTANT:
value_release ((Value *)expr->constant.value);
break;
case GNM_EXPR_OP_CELLREF:
break;
case GNM_EXPR_OP_ANY_UNARY:
do_gnm_expr_unref (expr->unary.value);
break;
case GNM_EXPR_OP_ARRAY:
if (expr->array.x == 0 && expr->array.y == 0) {
if (expr->array.corner.value)
value_release (expr->array.corner.value);
do_gnm_expr_unref (expr->array.corner.expr);
}
break;
case GNM_EXPR_OP_SET:
gnm_expr_list_unref (expr->set.set);
break;
default:
g_warning ("do_gnm_expr_unref error.");
break;
......@@ -433,6 +430,7 @@ gnm_expr_equal (GnmExpr const *a, GnmExpr const *b)
return FALSE;
switch (a->any.oper) {
case GNM_EXPR_OP_RANGE_CTOR:
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);
......@@ -485,58 +483,6 @@ gnm_expr_equal (GnmExpr const *a, GnmExpr const *b)
return FALSE;
}
/**
* gnm_expr_implicit_intersection :
* @ei: EvalInfo containing valid fd!
* @v: a VALUE_CELLRANGE
*
* 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.
**/
Value *
gnm_expr_implicit_intersection (EvalPos const *pos, Value *v)
{
Value *res = NULL;
Range rng;
Sheet *start_sheet, *end_sheet;
/* handle inverted ranges */
value_cellrange_normalize (pos, v, &start_sheet, &end_sheet, &rng);
if (start_sheet == end_sheet) {
if (rng.start.row == rng.end.row) {
int const c = pos->eval.col;
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);
}
}
if (rng.start.col == rng.end.col) {
int const r = pos->eval.row;
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);
}
}
}
value_release (v);
return res;
}
/**
* gnm_expr_array_intersection :
* @v: a VALUE_ARRAY
......@@ -566,6 +512,71 @@ cb_range_eval (Sheet *sheet, int col, int row, Cell *cell, void *ignore)
return NULL;
}
static Cell *
expr_array_corner (GnmExpr const *expr,
Sheet const *sheet, CellPos const *pos)
{
Cell *corner = sheet_cell_get (sheet,
pos->col - expr->array.x, pos->row - expr->array.y);
/* Sanity check incase the corner gets removed for some reason */
g_return_val_if_fail (corner != NULL, NULL);
g_return_val_if_fail (cell_has_expr (corner), NULL);
g_return_val_if_fail (corner->base.expression != (void *)0xdeadbeef, NULL);
g_return_val_if_fail (corner->base.expression->any.oper == GNM_EXPR_OP_ARRAY, NULL);
g_return_val_if_fail (corner->base.expression->array.x == 0, NULL);
g_return_val_if_fail (corner->base.expression->array.y == 0, NULL);
return corner;
}
static gboolean
gnm_expr_extract_ref (CellRef *res, GnmExpr const *expr, EvalPos const *pos)
{
switch (expr->any.oper) {
case GNM_EXPR_OP_FUNCALL : {
gboolean failed = TRUE;
Value *v;
FunctionEvalInfo ei;
ei.pos = pos;
ei.func_call = (GnmExprFunction const *)expr;
v = function_call_with_list (&ei, expr->func.arg_list);
if (v != NULL) {
if (v->type == VALUE_CELLRANGE &&
cellref_equal (&v->v_range.cell.a, &v->v_range.cell.b)) {
*res = v->v_range.cell.a;
failed = FALSE;
}
value_release (v);
}
return failed;
}
case GNM_EXPR_OP_CELLREF :
*res = expr->cellref.ref;
return FALSE;
case GNM_EXPR_OP_CONSTANT: {
Value const *v = expr->constant.value;
if (v->type == VALUE_CELLRANGE &&
cellref_equal (&v->v_range.cell.a, &v->v_range.cell.b)) {
*res = v->v_range.cell.a;
return FALSE;
}
return TRUE;
}
case GNM_EXPR_OP_NAME:
if (!expr->name.name->active || expr->name.name->builtin)
return TRUE;
return gnm_expr_extract_ref (res, expr->name.name->t.expr_tree, pos);
default :
break;
}
return TRUE;
}
static Value *
expr_eval_real (GnmExpr const *expr, EvalPos const *pos,
GnmExprEvalFlags flags)
......@@ -587,7 +598,7 @@ expr_eval_real (GnmExpr const *expr, EvalPos const *pos,
a = expr_eval_real (expr->binary.value_a, pos, flags);
if (a != NULL) {
if (a->type == VALUE_CELLRANGE) {
a = gnm_expr_implicit_intersection (pos, a);
a = value_intersection (a, pos);
if (a == NULL)
return value_new_error (pos, gnumeric_err_VALUE);
} else if (a->type == VALUE_ARRAY) {
......@@ -602,7 +613,7 @@ expr_eval_real (GnmExpr const *expr, EvalPos const *pos,
if (b != NULL) {
Value *res = NULL;
if (b->type == VALUE_CELLRANGE) {
b = gnm_expr_implicit_intersection (pos, b);
b = value_intersection (b, pos);
if (b == NULL)
res = value_new_error (pos, gnumeric_err_VALUE);
} else if (b->type == VALUE_ARRAY) {
......@@ -692,7 +703,7 @@ expr_eval_real (GnmExpr const *expr, EvalPos const *pos,
/* Handle implicit intersection */
if (a->type == VALUE_CELLRANGE) {
a = gnm_expr_implicit_intersection (pos, a);
a = value_intersection (a, pos);
if (a == NULL)
return value_new_error (pos, gnumeric_err_VALUE);
} else if (a->type == VALUE_ARRAY) {
......@@ -724,7 +735,7 @@ expr_eval_real (GnmExpr const *expr, EvalPos const *pos,
/* Handle implicit intersection */
if (b->type == VALUE_CELLRANGE) {
b = gnm_expr_implicit_intersection (pos, a);
b = value_intersection (a, pos);
if (b == NULL)
return value_new_error (pos, gnumeric_err_VALUE);
} else if (b->type == VALUE_ARRAY) {
......@@ -851,7 +862,7 @@ expr_eval_real (GnmExpr const *expr, EvalPos const *pos,
/* Handle implicit intersection */
if (a->type == VALUE_CELLRANGE) {
a = gnm_expr_implicit_intersection (pos, a);
a = value_intersection (a, pos);
if (a == NULL)
return value_new_error (pos, gnumeric_err_VALUE);
} else if (a->type == VALUE_ARRAY) {
......@@ -1074,6 +1085,16 @@ expr_eval_real (GnmExpr const *expr, EvalPos const *pos,
}
case GNM_EXPR_OP_SET:
g_warning ("Not implemented until 1.1");
break;
case GNM_EXPR_OP_RANGE_CTOR: {
CellRef a, b;
if (gnm_expr_extract_ref (&a, expr->binary.value_a, pos) ||
gnm_expr_extract_ref (&b, expr->binary.value_b, pos))
return value_new_error (pos, gnumeric_err_REF);
return value_new_cellrange (&a, &b, pos->eval.col, pos->eval.row);
}
break;
}
return value_new_error (pos, _("Unknown evaluation error"));
......@@ -1143,7 +1164,8 @@ do_expr_as_string (GnmExpr const *expr, ParsePos const *pp,
{ "+", 5, 0, 0 }, /* Unary + */
{ "%", 5, 0, 0 }, /* Percentage (NOT MODULO) */
{ NULL, 0, 0, 0 }, /* Array */
{ NULL, 0, 0, 0 } /* Set */
{ NULL, 0, 0, 0 }, /* Set */
{ NULL, 0, 0, 0 } /* Range Ctor */
};
int const op = expr->any.oper;
......@@ -1280,6 +1302,19 @@ do_expr_as_string (GnmExpr const *expr, ParsePos const *pp,
case GNM_EXPR_OP_SET:
return gnm_expr_list_as_string (expr->set.set, pp);
case GNM_EXPR_OP_RANGE_CTOR: {
char *a, *b, *res;
a = do_expr_as_string (expr->binary.value_a, pp, 0);
b = do_expr_as_string (expr->binary.value_b, pp, 0);
res = g_strconcat (a, ":", b, NULL);
g_free (a);
g_free (b);
return res;
}
}
g_assert_not_reached ();
......@@ -1529,6 +1564,7 @@ gnm_expr_rewrite (GnmExpr const *expr, GnmExprRewriteInfo const *rwinfo)
g_return_val_if_fail (expr != NULL, NULL);
switch (expr->any.oper) {
case GNM_EXPR_OP_RANGE_CTOR:
case GNM_EXPR_OP_ANY_BINARY: {
GnmExpr const *a = gnm_expr_rewrite (expr->binary.value_a, rwinfo);
GnmExpr const *b = gnm_expr_rewrite (expr->binary.value_b, rwinfo);
......@@ -2025,6 +2061,7 @@ ets_hash (gconstpointer key)
guint h = (guint)(expr->any.oper);
switch (expr->any.oper){
case GNM_EXPR_OP_RANGE_CTOR:
case GNM_EXPR_OP_ANY_BINARY:
return ((GPOINTER_TO_INT (expr->binary.value_a) * 7) ^
(GPOINTER_TO_INT (expr->binary.value_b) * 3) ^
......@@ -2080,6 +2117,7 @@ ets_equal (gconstpointer _a, gconstpointer _b)
return FALSE;
switch (ea->any.oper){
case GNM_EXPR_OP_RANGE_CTOR:
case GNM_EXPR_OP_ANY_BINARY:
return (ea->binary.value_a == eb->binary.value_a &&
ea->binary.value_b == eb->binary.value_b);
......@@ -2149,6 +2187,7 @@ expr_tree_sharer_share (ExprTreeSharer *es, GnmExpr const *e)
/* First share all sub-expressions. */
switch (e->any.oper) {
case GNM_EXPR_OP_RANGE_CTOR:
case GNM_EXPR_OP_ANY_BINARY:
((GnmExpr*)e)->binary.value_a =
expr_tree_sharer_share (es, e->binary.value_a);
......
......@@ -30,7 +30,8 @@ typedef enum {
GNM_EXPR_OP_UNARY_PLUS, /* Mark as positive */
GNM_EXPR_OP_PERCENTAGE, /* Percentage (value/100) */
GNM_EXPR_OP_ARRAY, /* Array access */
GNM_EXPR_OP_SET /* A set of expressions */
GNM_EXPR_OP_SET, /* A set of expressions */
GNM_EXPR_OP_RANGE_CTOR /* A constructed range eg A1:index(1,2) */
} GnmExprOp;
/* Shorthands for case statements. Easy to read, easy to maintain. */
......@@ -40,18 +41,18 @@ typedef enum {
case GNM_EXPR_OP_EXP: case GNM_EXPR_OP_CAT
#define GNM_EXPR_OP_ANY_UNARY GNM_EXPR_OP_UNARY_NEG: case GNM_EXPR_OP_UNARY_PLUS : case GNM_EXPR_OP_PERCENTAGE
GnmExpr const *gnm_expr_new_constant (Value *v);
GnmExpr const *gnm_expr_new_unary (GnmExprOp op, GnmExpr const *e);
GnmExpr const *gnm_expr_new_binary (GnmExpr const *l, GnmExprOp op,
GnmExpr const *r);
GnmExpr const *gnm_expr_new_funcall (FunctionDefinition *func,
GnmExprList *args);
GnmExpr const *gnm_expr_new_name (GnmNamedExpr *name,
Sheet *sheet_scope, Workbook *wb_scope);
GnmExpr const *gnm_expr_new_cellref (CellRef const *cr);
GnmExpr const *gnm_expr_new_array (int x, int y, int cols, int rows,
GnmExpr const *expr);
GnmExpr const *gnm_expr_new_set (GnmExprList *args);
GnmExpr const *gnm_expr_new_constant (Value *v);
GnmExpr const *gnm_expr_new_unary (GnmExprOp op, GnmExpr const *e);
GnmExpr const *gnm_expr_new_binary (GnmExpr const *l, GnmExprOp op,
GnmExpr const *r);
GnmExpr const *gnm_expr_new_funcall (FunctionDefinition *func,
GnmExprList *args);
GnmExpr const *gnm_expr_new_name (GnmNamedExpr *name,
Sheet *sheet_scope, Workbook *wb_scope);
GnmExpr const *gnm_expr_new_cellref (CellRef const *cr);
GnmExpr const *gnm_expr_new_array (int x, int y, int cols, int rows,
GnmExpr const *expr);
GnmExpr const *gnm_expr_new_set (GnmExprList *args);
GnmExpr const *gnm_expr_first_func (GnmExpr const *expr);
Value *gnm_expr_get_range (GnmExpr const *expr) ;
......@@ -103,7 +104,6 @@ Value *gnm_expr_eval (GnmExpr const *expr, EvalPos const *pos,
/* minor utilities, these _will_ change to support implicit iteration */
Value *gnm_expr_array_intersection (Value *v);
Value *gnm_expr_implicit_intersection (EvalPos const *pos, Value *v);
/*****************************************************************************/
......
......@@ -735,7 +735,7 @@ function_marshal_arg (FunctionEvalInfo *ei,
case 'f':
case 'b':
if (v->type == VALUE_CELLRANGE) {
v = gnm_expr_implicit_intersection (ei->pos, v);
v = value_intersection (v, ei->pos);
if (v == NULL)
break;
} else if (v->type == VALUE_ARRAY) {
......@@ -767,7 +767,7 @@ function_marshal_arg (FunctionEvalInfo *ei,
case 's':
if (v->type == VALUE_CELLRANGE) {
v = gnm_expr_implicit_intersection (ei->pos, v);
v = value_intersection (v, ei->pos);
if (v == NULL)
break;
} else if (v->type == VALUE_ARRAY) {
......@@ -825,7 +825,7 @@ function_marshal_arg (FunctionEvalInfo *ei,
case 'S':
if (v->type == VALUE_CELLRANGE) {