[gnumeric] Arrays: code cleanup.



commit c5c51af8adc59cda17ef8c074b4ee87d1a99910f
Author: Morten Welinder <terra gnome org>
Date:   Sat Dec 30 17:38:25 2017 -0500

    Arrays: code cleanup.
    
    This moves us closer to making array corners and elements part of GnmExprTop
    as opposed to the current state where they are in GnmExpr, but are only
    allowed at top level.
    
    Specifically, with this commit, we now query attributes of array
    corners and elements mostly with a texpr.  Mostly.
    
    A nice side effect is that many expr-impl.h includes can be removed.  We
    have too many of those.

 ChangeLog                               |   10 ++
 NEWS                                    |    1 +
 plugins/excel/ms-excel-write.c          |   20 ++--
 plugins/excel/ms-formula-write.c        |   15 +-
 plugins/excel/ms-formula-write.h        |    2 +-
 plugins/excel/xlsx-utils.c              |    7 +-
 plugins/excel/xlsx-write.c              |   10 +-
 plugins/excelplugins/excelplugins.c     |   13 +-
 plugins/fn-lookup/functions.c           |    6 +-
 plugins/guile/plugin.c                  |    5 +-
 plugins/openoffice/openoffice-write.c   |   10 +-
 plugins/sylk/sylk-write.c               |   17 ++-
 src/cell.c                              |   47 +++---
 src/cell.h                              |    2 -
 src/cmd-edit.c                          |    1 -
 src/dependent.c                         |   23 ++--
 src/expr.c                              |  238 +++++++++++++++++++------------
 src/expr.h                              |    6 +-
 src/func-builtin.c                      |   24 ++--
 src/func.c                              |   16 ++-
 src/func.h                              |    4 +
 src/position.c                          |   28 +++--
 src/position.h                          |   10 +-
 src/sheet-autofill.c                    |   20 ++--
 src/sheet.c                             |   15 +-
 src/style-conditions.c                  |    9 +-
 src/wbc-gtk.c                           |    6 +-
 src/widgets/gnm-validation-combo-view.c |    1 -
 src/workbook-view.c                     |   12 +-
 29 files changed, 333 insertions(+), 245 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 5926eff..b31b4bf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2017-12-30  Morten Welinder  <terra gnome org>
+
+       * src/expr.c (gnm_expr_top_get_array_corner): Remove.  All callers
+       changed.
+       (gnm_expr_top_get_array_size, gnm_expr_top_get_array_value)
+       (gnm_expr_top_get_array_expr): New functions.
+
+       * src/cell.c (gnm_cell_is_array_corner): Remove.  All callers
+       changed.
+
 2017-12-29  Morten Welinder  <terra gnome org>
 
        * src/ssdiff.c (diff_names): Fix checks for inserted or removed
diff --git a/NEWS b/NEWS
index 992f697..84e8f4c 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,7 @@ Gnumeric 1.12.39
 Morten:
        * Fix ssdiff problem.  [#792038]
        * Fix ISREF.
+       * Some internal array formula code cleanups.
 
 --------------------------------------------------------------------------
 Gnumeric 1.12.38
diff --git a/plugins/excel/ms-excel-write.c b/plugins/excel/ms-excel-write.c
index ce4832d..7e9c5c7 100644
--- a/plugins/excel/ms-excel-write.c
+++ b/plugins/excel/ms-excel-write.c
@@ -3507,7 +3507,6 @@ excel_write_FORMULA (ExcelWriteState *ewb, ExcelWriteSheet *esheet, GnmCell cons
        gint     col, row;
        GnmValue   *v;
        GnmExprTop const *texpr;
-       GnmExprArrayCorner const *corner;
 
        g_return_if_fail (ewb);
        g_return_if_fail (cell);
@@ -3575,16 +3574,19 @@ excel_write_FORMULA (ExcelWriteState *ewb, ExcelWriteSheet *esheet, GnmCell cons
 
        ms_biff_put_commit (ewb->bp);
 
-       corner = gnm_expr_top_get_array_corner (texpr);
-       if (corner) {
+       if (gnm_expr_top_is_array_corner (texpr)) {
                GnmCellPos c_in, r_in;
-               if (gnm_expr_is_data_table (corner->expr, &c_in, &r_in)) {
+               int cols, rows;
+
+               gnm_expr_top_get_array_size (texpr, &cols, &rows);
+
+               if (gnm_expr_is_data_table (gnm_expr_top_get_array_expr (texpr), &c_in, &r_in)) {
                        guint16 flags = 0;
                        guint8 *data = ms_biff_put_len_next (ewb->bp, BIFF_TABLE_v2, 16);
                        GSF_LE_SET_GUINT16 (data + 0, cell->pos.row);
-                       GSF_LE_SET_GUINT16 (data + 2, cell->pos.row + corner->rows-1);
+                       GSF_LE_SET_GUINT16 (data + 2, cell->pos.row + rows-1);
                        GSF_LE_SET_GUINT16 (data + 4, cell->pos.col);
-                       GSF_LE_SET_GUINT16 (data + 5, cell->pos.col + corner->cols-1);
+                       GSF_LE_SET_GUINT16 (data + 5, cell->pos.col + cols-1);
 
                        if ((c_in.col != 0 || c_in.row != 0) &&
                            (r_in.col != 0 || r_in.row != 0)) {
@@ -3614,14 +3616,14 @@ excel_write_FORMULA (ExcelWriteState *ewb, ExcelWriteSheet *esheet, GnmCell cons
                } else {
                        ms_biff_put_var_next (ewb->bp, BIFF_ARRAY_v2);
                        GSF_LE_SET_GUINT16 (data+0, cell->pos.row);
-                       GSF_LE_SET_GUINT16 (data+2, cell->pos.row + corner->rows-1);
+                       GSF_LE_SET_GUINT16 (data+2, cell->pos.row + rows-1);
                        GSF_LE_SET_GUINT16 (data+4, cell->pos.col);
-                       GSF_LE_SET_GUINT16 (data+5, cell->pos.col + corner->cols-1);
+                       GSF_LE_SET_GUINT16 (data+5, cell->pos.col + cols-1);
                        GSF_LE_SET_GUINT16 (data+6, 0x0); /* alwaysCalc & calcOnLoad */
                        GSF_LE_SET_GUINT32 (data+8, 0);
                        GSF_LE_SET_GUINT16 (data+12, 0); /* bogus len, fill in later */
                        ms_biff_put_var_write (ewb->bp, data, 14);
-                       len = excel_write_array_formula (ewb, corner,
+                       len = excel_write_array_formula (ewb, gnm_expr_top_get_array_expr (texpr),
                                                         esheet->gnum_sheet, col, row);
 
                        ms_biff_put_var_seekto (ewb->bp, 12);
diff --git a/plugins/excel/ms-formula-write.c b/plugins/excel/ms-formula-write.c
index de93246..d1c080d 100644
--- a/plugins/excel/ms-formula-write.c
+++ b/plugins/excel/ms-formula-write.c
@@ -871,10 +871,11 @@ write_node (PolishData *pd, GnmExpr const *expr, int paren_level,
 
                ptg = FORMULA_PTG_EXPR;
                if (pd->sheet != NULL) {
-                       GnmExprArrayCorner const *corner = gnm_cell_is_array_corner (
-                               sheet_cell_get (pd->sheet, pd->col - x, pd->row - y));
-                       if (NULL != corner &&
-                           gnm_expr_is_data_table (corner->expr, NULL, NULL))
+                       GnmCell const *ccell =
+                               sheet_cell_get (pd->sheet, pd->col - x, pd->row - y);
+                       if (ccell &&
+                           gnm_expr_top_is_array_corner (ccell->base.texpr) &&
+                           gnm_expr_is_data_table (gnm_expr_top_get_array_expr (ccell->base.texpr), NULL, 
NULL))
                                ptg = FORMULA_PTG_TBL;
                }
 
@@ -980,7 +981,7 @@ write_arrays (PolishData *pd)
 
 guint32
 excel_write_array_formula (ExcelWriteState *ewb,
-                          GnmExprArrayCorner const *array,
+                          GnmExpr const *array_expr,
                           Sheet *sheet, int fn_col, int fn_row)
 {
        PolishData pd;
@@ -988,7 +989,7 @@ excel_write_array_formula (ExcelWriteState *ewb,
        guint32 len;
 
        g_return_val_if_fail (ewb, 0);
-       g_return_val_if_fail (array, 0);
+       g_return_val_if_fail (array_expr, 0);
 
        pd.col     = fn_col;
        pd.row     = fn_row;
@@ -1000,7 +1001,7 @@ excel_write_array_formula (ExcelWriteState *ewb,
        pd.allow_sheetless_ref = TRUE;
 
        start = ewb->bp->curpos;
-       write_node (&pd, array->expr, 0, XL_ROOT);
+       write_node (&pd, array_expr, 0, XL_ROOT);
        len = ewb->bp->curpos - start;
 
        write_arrays (&pd);
diff --git a/plugins/excel/ms-formula-write.h b/plugins/excel/ms-formula-write.h
index 150e8e8..9e09641 100644
--- a/plugins/excel/ms-formula-write.h
+++ b/plugins/excel/ms-formula-write.h
@@ -29,7 +29,7 @@ guint32 excel_write_formula    (ExcelWriteState *ewb,
                                Sheet *sheet, int fn_col, int fn_row,
                                ExcelFuncContext context);
 guint32 excel_write_array_formula (ExcelWriteState *ewb,
-                                  GnmExprArrayCorner const *array,
+                                  GnmExpr const *array_expr,
                                   Sheet *sheet, int fn_col, int fn_row);
 
 void excel_write_prep_expressions (ExcelWriteState *ewb);
diff --git a/plugins/excel/xlsx-utils.c b/plugins/excel/xlsx-utils.c
index 13b673e..3673272 100644
--- a/plugins/excel/xlsx-utils.c
+++ b/plugins/excel/xlsx-utils.c
@@ -32,12 +32,12 @@
 #include "workbook.h"
 #include "sheet.h"
 #include "func.h"
-#include <expr-impl.h>
 #include "gnm-format.h"
 #include <goffice/goffice.h>
 #include <glib-object.h>
 #include <string.h>
 #include <expr.h>
+#include <expr-impl.h>
 #include <value.h>
 
 typedef struct {
@@ -170,7 +170,8 @@ static void
 xlsx_func_map_out (GnmConventionsOut *out, GnmExprFunction const *func)
 {
        XLSXExprConventions const *xconv = (XLSXExprConventions const *)(out->convs);
-       char const *name = gnm_func_get_name (func->func, FALSE);
+       GnmFunc const *gfunc = gnm_expr_get_func_def ((GnmExpr *)func);
+       char const *name = gnm_func_get_name (gfunc, FALSE);
        gboolean (*handler) (GnmConventionsOut *out, GnmExprFunction const *func);
 
        handler = g_hash_table_lookup (xconv->xlfn_handler_map, name);
@@ -182,7 +183,7 @@ xlsx_func_map_out (GnmConventionsOut *out, GnmExprFunction const *func)
                if (new_name == NULL) {
                                char *new_u_name;
                                new_u_name = g_ascii_strup (name, -1);
-                               if (func->func->impl_status ==
+                               if (gfunc->impl_status ==
                                    GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC)
                                        g_string_append (target, "_xlfngnumeric.");
                                /* LO & friends use _xlfnodf */
diff --git a/plugins/excel/xlsx-write.c b/plugins/excel/xlsx-write.c
index 2ebff68..3609471 100644
--- a/plugins/excel/xlsx-write.c
+++ b/plugins/excel/xlsx-write.c
@@ -41,7 +41,6 @@
 #include "value.h"
 #include "cell.h"
 #include "expr.h"
-#include "expr-impl.h"
 #include "func.h"
 #include "style-color.h"
 #include "validation.h"
@@ -1540,7 +1539,6 @@ xlsx_write_cells (XLSXWriteState *state, GsfXMLOut *xml,
        char *content;
        GnmParsePos pp;
        GnmExprTop const *texpr;
-       GnmExprArrayCorner const *array;
        char *cheesy_span = g_strdup_printf ("%d:%d", extent->start.col+1, extent->end.col+1);
        Sheet *sheet = (Sheet *)state->sheet;
        GPtrArray *all_cells = sheet_cells (sheet, extent);
@@ -1693,11 +1691,13 @@ xlsx_write_cells (XLSXWriteState *state, GsfXMLOut *xml,
                                        if (!gnm_expr_top_is_array_elem (texpr, NULL, NULL)) {
                                                gsf_xml_out_start_element (xml, "f");
 
-                                               array = gnm_expr_top_get_array_corner (texpr);
-                                               if (NULL != array) {
+                                               if (gnm_expr_top_is_array_corner (texpr)) {
                                                        GnmRange r;
+                                                       int cols, rows;
+
+                                                       gnm_expr_top_get_array_size (texpr, &cols, &rows);
                                                        range_init_cellpos_size (&r, &cell->pos,
-                                                               array->cols, array->rows);
+                                                               cols, rows);
                                                        gsf_xml_out_add_cstr_unchecked (xml, "t", "array");
                                                        xlsx_add_range (xml, "ref", &r);
                                                }
diff --git a/plugins/excelplugins/excelplugins.c b/plugins/excelplugins/excelplugins.c
index df589d3..8ce9c63 100644
--- a/plugins/excelplugins/excelplugins.c
+++ b/plugins/excelplugins/excelplugins.c
@@ -40,7 +40,6 @@
 #include <workbook.h>
 #include <sheet.h>
 #include <cell.h>
-#include <expr-impl.h>
 #include <string.h>
 
 #ifdef WIN32
@@ -490,17 +489,17 @@ genericXLLFunction (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
        GnmValue *g = NULL;
        guint i,m;
        const XLLFunctionInfo*info = NULL;
+       GnmFunc const *gfunc = gnm_eval_info_get_func (ei);
+
        g_assert (NULL != xll_function_info_map);
-       info=g_tree_lookup (xll_function_info_map,ei->func_call->func->name);
+       info=g_tree_lookup (xll_function_info_map, gfunc->name);
        g_assert (NULL != info);
-       m=ei->func_call->argc;
-       if ( m > MAXIMUM_NUMBER_OF_EXCEL_FUNCTION_ARGUMENTS )
-               m = MAXIMUM_NUMBER_OF_EXCEL_FUNCTION_ARGUMENTS;
+       m = gnm_eval_info_get_arg_count (ei);
+       m = MAX (m, MAXIMUM_NUMBER_OF_EXCEL_FUNCTION_ARGUMENTS);
        for (i = 0; i < m; ++i)
                copy_construct_xloper_from_gnm_value (x+i,argv[i],ei);
        m = info->number_of_arguments;
-       if ( m > MAXIMUM_NUMBER_OF_EXCEL_FUNCTION_ARGUMENTS )
-               m = MAXIMUM_NUMBER_OF_EXCEL_FUNCTION_ARGUMENTS;
+       m = MAX (m, MAXIMUM_NUMBER_OF_EXCEL_FUNCTION_ARGUMENTS);
        for (; i < m; ++i)
                x[i].xltype=xltypeMissing;
        func = (XLLFunctionWithVarArgs)info->xll_function;
diff --git a/plugins/fn-lookup/functions.c b/plugins/fn-lookup/functions.c
index a7783ed..25b69a9 100644
--- a/plugins/fn-lookup/functions.c
+++ b/plugins/fn-lookup/functions.c
@@ -1470,7 +1470,7 @@ gnumeric_column (GnmFuncEvalInfo *ei, GnmValue const * const *args)
        if (ref == NULL) {
                col   = ei->pos->eval.col + 1; /* user visible counts from 0 */
                if (eval_pos_is_array_context (ei->pos))
-                       width = ei->pos->array->cols;
+                       gnm_expr_top_get_array_size (ei->pos->array_texpr, &width, NULL);
                else
                        return value_new_int (col);
        } else if (VALUE_IS_CELLRANGE (ref)) {
@@ -1620,8 +1620,8 @@ gnumeric_row (GnmFuncEvalInfo *ei, GnmValue const * const *args)
 
        if (ref == NULL) {
                row   = ei->pos->eval.row + 1; /* user visible counts from 0 */
-               if (ei->pos->array != NULL)
-                       n = ei->pos->array->rows;
+               if (eval_pos_is_array_context (ei->pos))
+                       gnm_expr_top_get_array_size (ei->pos->array_texpr, NULL, &n);
                else
                        return value_new_int (row);
        } else if (VALUE_IS_CELLRANGE (ref)) {
diff --git a/plugins/guile/plugin.c b/plugins/guile/plugin.c
index 9f1c878..20788ff 100644
--- a/plugins/guile/plugin.c
+++ b/plugins/guile/plugin.c
@@ -35,7 +35,6 @@
 #include <goffice/goffice.h>
 #include <gnm-plugin.h>
 #include "expr.h"
-#include "expr-impl.h"
 #include "gutils.h"
 #include "func.h"
 #include "cell.h"
@@ -144,10 +143,8 @@ func_marshal_func (GnmFuncEvalInfo *ei, GnmValue *argv[])
        int i, min, max;
 
        g_return_val_if_fail (ei != NULL, NULL);
-       g_return_val_if_fail (ei->func_call != NULL, NULL);
-       g_return_val_if_fail (ei->func_call->func != NULL, NULL);
 
-       fndef = ei->func_call->func;
+       fndef = gnm_eval_info_get_func (ei);
        function_def_count_args (fndef, &min, &max);
 
        function = (SCM) gnm_func_get_user_data (fndef);
diff --git a/plugins/openoffice/openoffice-write.c b/plugins/openoffice/openoffice-write.c
index 0b67808..305b780 100644
--- a/plugins/openoffice/openoffice-write.c
+++ b/plugins/openoffice/openoffice-write.c
@@ -3505,16 +3505,16 @@ odf_write_cell (GnmOOExport *state, GnmCell *cell, GnmRange const *merge_range,
                        GnmParsePos pp;
 
                        if (gnm_cell_is_array (cell)) {
-                               GnmExprArrayCorner const *ac;
+                               if (gnm_expr_top_is_array_corner (cell->base.texpr)) {
+                                       int cols, rows;
 
-                               ac = gnm_expr_top_get_array_corner (cell->base.texpr);
-                               if (ac != NULL) {
+                                       gnm_expr_top_get_array_size (cell->base.texpr, &cols, &rows);
                                        gsf_xml_out_add_uint (state->xml,
                                                              TABLE "number-matrix-columns-spanned",
-                                                             (unsigned int)(ac->cols));
+                                                             (unsigned int)cols);
                                        gsf_xml_out_add_uint (state->xml,
                                                              TABLE "number-matrix-rows-spanned",
-                                                             (unsigned int)(ac->rows));
+                                                             (unsigned int)rows);
                                }
                        }
 
diff --git a/plugins/sylk/sylk-write.c b/plugins/sylk/sylk-write.c
index 5e5d805..3080335 100644
--- a/plugins/sylk/sylk-write.c
+++ b/plugins/sylk/sylk-write.c
@@ -27,7 +27,6 @@
 #include "sheet.h"
 #include "sheet-style.h"
 #include "expr.h"
-#include "expr-impl.h"
 #include "value.h"
 #include "cell.h"
 #include "mstyle.h"
@@ -119,7 +118,6 @@ cb_sylk_write_cell (GnmCellIter const *iter, SylkWriter *state)
 {
        GnmValue const *v;
        GnmExprTop const *texpr;
-       GnmExprArrayCorner const *array;
 
        if (iter->pp.eval.row != state->cur_row)
                gsf_output_printf (state->output, "C;Y%d;X%d",
@@ -129,7 +127,8 @@ cb_sylk_write_cell (GnmCellIter const *iter, SylkWriter *state)
                gsf_output_printf (state->output, "C;X%d",
                        iter->pp.eval.col + 1);
 
-       if (NULL != (v = iter->cell->value)) {
+       v = iter->cell->value;
+       if (v) {
                if (VALUE_IS_STRING (v)) {
                        gsf_output_write (state->output, 3, ";K\"");
                        sylk_write (state, v->v_str.val->str);
@@ -143,11 +142,15 @@ cb_sylk_write_cell (GnmCellIter const *iter, SylkWriter *state)
                } /* ignore the rest */
        }
 
-       if (NULL != (texpr = iter->cell->base.texpr)) {
-               if (NULL != (array = gnm_expr_top_get_array_corner (texpr))) {
+       texpr = iter->cell->base.texpr;
+       if (texpr) {
+               if (gnm_expr_top_is_array_corner (texpr)) {
+                       int cols, rows;
+                       gnm_expr_top_get_array_size (texpr, &cols, &rows);
+
                        gsf_output_printf (state->output, ";R%d;C%d;M",
-                               iter->pp.eval.row + array->rows,
-                               iter->pp.eval.col + array->cols);
+                                          iter->pp.eval.row + rows,
+                                          iter->pp.eval.col + cols);
                } else if (gnm_expr_top_is_array_elem (texpr, NULL, NULL)) {
                        gsf_output_write (state->output, 2, ";I");
                        texpr = NULL;
diff --git a/src/cell.c b/src/cell.c
index 4051516..d693476 100644
--- a/src/cell.c
+++ b/src/cell.c
@@ -15,7 +15,6 @@
 #include "workbook.h"
 #include "sheet.h"
 #include "expr.h"
-#include "expr-impl.h"
 #include "rendered-value.h"
 #include "value.h"
 #include "style.h"
@@ -461,8 +460,8 @@ gboolean
 gnm_cell_array_bound (GnmCell const *cell, GnmRange *res)
 {
        GnmExprTop const *texpr;
-       GnmExprArrayCorner const *array;
        int x, y;
+       int cols, rows;
 
        if (NULL == cell || !gnm_cell_has_expr (cell))
                return FALSE;
@@ -479,24 +478,17 @@ gnm_cell_array_bound (GnmCell const *cell, GnmRange *res)
                texpr = cell->base.texpr;
        }
 
-       array = gnm_expr_top_get_array_corner (texpr);
-       if (!array)
+       if (!gnm_expr_top_is_array_corner (texpr))
                return FALSE;
 
+       gnm_expr_top_get_array_size (texpr, &cols, &rows);
+
        range_init (res, cell->pos.col, cell->pos.row,
-               cell->pos.col + array->cols - 1,
-               cell->pos.row + array->rows - 1);
+               cell->pos.col + cols - 1,
+               cell->pos.row + rows - 1);
        return TRUE;
 }
 
-GnmExprArrayCorner const *
-gnm_cell_is_array_corner (GnmCell const *cell)
-{
-       return cell && gnm_cell_has_expr (cell)
-               ? gnm_expr_top_get_array_corner (cell->base.texpr)
-               : NULL;
-}
-
 /**
  * gnm_cell_is_array:
  * @cell: #GnmCell const *
@@ -520,15 +512,18 @@ gnm_cell_is_array (GnmCell const *cell)
 gboolean
 gnm_cell_is_nonsingleton_array (GnmCell const *cell)
 {
-       GnmExprArrayCorner const *corner;
+       int cols, rows;
 
        if ((cell == NULL) || !gnm_cell_has_expr (cell))
                return FALSE;
        if (gnm_expr_top_is_array_elem (cell->base.texpr, NULL, NULL))
                return TRUE;
 
-       corner  = gnm_expr_top_get_array_corner (cell->base.texpr);
-       return corner && (corner->cols > 1 || corner->rows > 1);
+       if (!gnm_expr_top_is_array_corner (cell->base.texpr))
+               return FALSE;
+
+       gnm_expr_top_get_array_size (cell->base.texpr, &cols, &rows);
+       return cols > 1 || rows > 1;
 }
 
 /***************************************************************************/
@@ -1021,7 +1016,7 @@ cb_set_array_value (GnmCellIter const *iter, gpointer user)
 void
 gnm_cell_convert_expr_to_value (GnmCell *cell)
 {
-       GnmExprArrayCorner const *array;
+       GnmExprTop const *texpr;
 
        g_return_if_fail (cell != NULL);
        g_return_if_fail (gnm_cell_has_expr (cell));
@@ -1030,19 +1025,23 @@ gnm_cell_convert_expr_to_value (GnmCell *cell)
        if (gnm_cell_expr_is_linked (cell))
                dependent_unlink (GNM_CELL_TO_DEP (cell));
 
-       array = gnm_expr_top_get_array_corner (cell->base.texpr);
-       if (array) {
+       texpr = cell->base.texpr;
+       if (gnm_expr_top_is_array_corner (texpr)) {
+               int rows, cols;
+
+               gnm_expr_top_get_array_size (texpr, &cols, &rows);
+
                sheet_foreach_cell_in_range (cell->base.sheet, CELL_ITER_ALL,
                                             cell->pos.col, cell->pos.row,
-                                            cell->pos.col + array->cols - 1,
-                                            cell->pos.row + array->rows - 1,
+                                            cell->pos.col + cols - 1,
+                                            cell->pos.row + rows - 1,
                                             cb_set_array_value,
-                                            array->value);
+                                            gnm_expr_top_get_array_value (texpr));
        } else {
                g_return_if_fail (!gnm_cell_is_array (cell));
        }
 
-       gnm_expr_top_unref (cell->base.texpr);
+       gnm_expr_top_unref (texpr);
        cell->base.texpr = NULL;
 }
 
diff --git a/src/cell.h b/src/cell.h
index 9760ff9..7c7d1bc 100644
--- a/src/cell.h
+++ b/src/cell.h
@@ -46,8 +46,6 @@ gboolean    gnm_cell_is_zero    (GnmCell const *cell);
 
 gboolean    gnm_cell_is_array    (GnmCell const *cell);
 gboolean    gnm_cell_is_nonsingleton_array (GnmCell const *cell);
-GnmExprArrayCorner const *
-           gnm_cell_is_array_corner  (GnmCell const *cell);
 gboolean    gnm_cell_array_bound         (GnmCell const *cell, GnmRange *res);
 
 /*
diff --git a/src/cmd-edit.c b/src/cmd-edit.c
index 9f0aea6..48e93da 100644
--- a/src/cmd-edit.c
+++ b/src/cmd-edit.c
@@ -32,7 +32,6 @@
 #include "sheet-view.h"
 #include "cell.h"
 #include "expr.h"
-#include "expr-impl.h"
 #include "dependent.h"
 #include "selection.h"
 #include "parse-util.h"
diff --git a/src/dependent.c b/src/dependent.c
index 6d2e6fd..652a25f 100644
--- a/src/dependent.c
+++ b/src/dependent.c
@@ -1140,9 +1140,8 @@ link_unlink_expr_dep (GnmEvalPos *ep, GnmExpr const *tree, gboolean qlink)
                /* Non-corner cells depend on the corner */
                GnmCellRef a;
                GnmCellPos const *pos = dependent_pos (ep->dep);
-               /* We cannot support array expressions unless
-                * we have a position.
-                */
+               // We cannot support array expressions unless we have
+               // a position.
                g_return_val_if_fail (pos != NULL, DEPENDENT_NO_FLAG);
 
                a.col_relative = a.row_relative = FALSE;
@@ -1154,8 +1153,11 @@ link_unlink_expr_dep (GnmEvalPos *ep, GnmExpr const *tree, gboolean qlink)
        }
 
        case GNM_EXPR_OP_ARRAY_CORNER: {
+               // It's mildly unclean to do this here.  We need the texpr, so get the cell.
+               GnmCellPos const *cpos = dependent_pos (ep->dep);
+               GnmCell const *cell = sheet_cell_get (ep->dep->sheet, cpos->col, cpos->row);
                GnmEvalPos pos = *ep;
-               pos.array = &tree->array_corner;
+               pos.array_texpr = cell->base.texpr;
                /* Corner cell depends on the contents of the expr */
                return link_unlink_expr_dep (&pos, tree->array_corner.expr, qlink);
        }
@@ -2039,15 +2041,16 @@ dependents_unrelocate (GSList *info)
                                 * is not really relevant.  eg when undoing a pasted
                                 * cut that was relocated but also saved to a buffer */
                                if (cell != NULL) {
-                                       GnmExprArrayCorner const *corner =
-                                               gnm_expr_top_get_array_corner (tmp->oldtree);
-                                       if (corner) {
+                                       if (gnm_expr_top_is_array_corner (tmp->oldtree)) {
+                                               int cols, rows;
+
+                                               gnm_expr_top_get_array_size (tmp->oldtree, &cols, &rows);
                                                gnm_cell_set_array_formula (tmp->u.pos.sheet,
                                                                            tmp->u.pos.eval.col,
                                                                            tmp->u.pos.eval.row,
-                                                                           tmp->u.pos.eval.col + 
corner->cols - 1,
-                                                                           tmp->u.pos.eval.row + 
corner->rows - 1,
-                                                                           gnm_expr_top_new (gnm_expr_copy 
(corner->expr)));
+                                                                           tmp->u.pos.eval.col + cols - 1,
+                                                                           tmp->u.pos.eval.row + rows - 1,
+                                                                           gnm_expr_top_new (gnm_expr_copy 
(gnm_expr_top_get_array_expr (tmp->oldtree))));
                                                cell_queue_recalc (cell);
                                                sheet_flag_status_update_cell (cell);
                                        } else
diff --git a/src/expr.c b/src/expr.c
index c05733b..c2b8af9 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -506,7 +506,10 @@ gnm_expr_free (GnmExpr const *expr)
 
        case GNM_EXPR_OP_ARRAY_CORNER:
                value_release (expr->array_corner.value);
-               gnm_expr_free (expr->array_corner.expr);
+               // A proper corner will not have NULL here, but we explicitly allow it
+               // during construction, so allow it here too.
+               if (expr->array_corner.expr)
+                       gnm_expr_free (expr->array_corner.expr);
                CHUNK_FREE (expression_pool_big, (gpointer)expr);
                break;
 
@@ -1518,67 +1521,11 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos,
                }
                return handle_empty (res, flags);
 
-       case GNM_EXPR_OP_ARRAY_CORNER: {
-               GnmEvalPos range_pos = *pos;
-               range_pos.array = &expr->array_corner;
-
-               a = gnm_expr_eval (expr->array_corner.expr, &range_pos,
-                       flags | GNM_EXPR_EVAL_PERMIT_NON_SCALAR);
-
-               value_release (expr->array_corner.value);
-
-               /* Store real result (cast away const)*/
-               ((GnmExpr*)expr)->array_corner.value = a;
-
-               if (a != NULL &&
-                   (VALUE_IS_CELLRANGE (a) || VALUE_IS_ARRAY (a))) {
-                       if (value_area_get_width (a, pos) <= 0 ||
-                           value_area_get_height (a, pos) <= 0)
-                               return value_new_error_NA (pos);
-                       a = (GnmValue *)value_area_get_x_y (a, 0, 0, pos);
-               }
-               return handle_empty ((a != NULL) ? value_dup (a) : NULL, flags);
-       }
-
-       case GNM_EXPR_OP_ARRAY_ELEM: {
-               /* The upper left corner manages the recalc of the expr */
-               GnmCell *corner = array_elem_get_corner (&expr->array_elem,
-                       pos->sheet, &pos->eval);
-               if (!corner ||
-                   !gnm_expr_top_is_array_corner (corner->base.texpr)) {
-                       g_warning ("Funky array setup.");
-                       return handle_empty (NULL, flags);
-               }
-
-               gnm_cell_eval (corner);
-               a = corner->base.texpr->expr->array_corner.value;
-               if (a == NULL)
-                       return handle_empty (NULL, flags);
-
-               if ((VALUE_IS_CELLRANGE (a) || VALUE_IS_ARRAY (a))) {
-                       int const num_x = value_area_get_width (a, pos);
-                       int const num_y = value_area_get_height (a, pos);
-                       int x = expr->array_elem.x;
-                       int y = expr->array_elem.y;
-
-                       /* Evaluate relative to the upper left corner */
-                       GnmEvalPos tmp_ep = *pos;
-                       tmp_ep.eval.col -= x;
-                       tmp_ep.eval.row -= y;
-
-                       /* If the src array is 1 element wide or tall we wrap */
-                       if (x >= 1 && num_x == 1)
-                               x = 0;
-                       if (y >= 1 && num_y == 1)
-                               y = 0;
-                       if (x >= num_x || y >= num_y)
-                               return value_new_error_NA (pos);
-
-                       a = (GnmValue *)value_area_get_x_y (a, x, y, &tmp_ep);
-               }
+       case GNM_EXPR_OP_ARRAY_CORNER:
+       case GNM_EXPR_OP_ARRAY_ELEM:
+               g_warning ("Unexpected array expressions encountered");
+               return value_new_error_VALUE (pos);
 
-               return handle_empty ((a != NULL) ? value_dup (a) : NULL, flags);
-       }
        case GNM_EXPR_OP_SET:
                if (flags & GNM_EXPR_EVAL_PERMIT_NON_SCALAR) {
                        int i;
@@ -1892,6 +1839,21 @@ gnm_expr_get_constant (GnmExpr const *expr)
        return expr->constant.value;
 }
 
+/**
+ * gnm_expr_get_cellref:
+ * @expr:
+ *
+ * If this expression consists of just a cell reference, return it.
+ */
+GnmCellRef const *
+gnm_expr_get_cellref (GnmExpr const *expr)
+{
+       if (GNM_EXPR_GET_OPER (expr) != GNM_EXPR_OP_CELLREF)
+               return NULL;
+
+       return &expr->cellref.ref;
+}
+
 
 typedef struct {
        GnmExprRelocateInfo const *details;
@@ -3110,28 +3072,109 @@ gnm_expr_top_is_volatile (GnmExprTop const *texpr)
 }
 
 
+static GnmValue *
+gnm_expr_top_eval_array_corner (GnmExprTop const *texpr,
+                               GnmEvalPos const *pos,
+                               GnmExprEvalFlags flags)
+{
+       GnmExpr const *expr = texpr->expr;
+       GnmEvalPos pos2;
+       GnmValue *a;
+
+       pos2 = *pos;
+       pos2.array_texpr = texpr;
+       a = gnm_expr_eval (expr->array_corner.expr, &pos2,
+                                    flags | GNM_EXPR_EVAL_PERMIT_NON_SCALAR);
+
+       value_release (expr->array_corner.value);
+
+       /* Store real result (cast away const)*/
+       ((GnmExpr*)expr)->array_corner.value = a;
+
+       if (a != NULL &&
+           (VALUE_IS_CELLRANGE (a) || VALUE_IS_ARRAY (a))) {
+               if (value_area_get_width (a, pos) <= 0 ||
+                   value_area_get_height (a, pos) <= 0)
+                       return value_new_error_NA (pos);
+               a = (GnmValue *)value_area_get_x_y (a, 0, 0, pos);
+       }
+       return handle_empty ((a != NULL) ? value_dup (a) : NULL, flags);
+}
+
+static GnmValue *
+gnm_expr_top_eval_array_elem (GnmExprTop const *texpr,
+                             GnmEvalPos const *pos,
+                             GnmExprEvalFlags flags)
+{
+       GnmExpr const *expr = texpr->expr;
+       /* The upper left corner manages the recalc of the expr */
+       GnmCell *corner = array_elem_get_corner (&expr->array_elem,
+                                                pos->sheet, &pos->eval);
+       GnmValue *a;
+
+       if (!corner ||
+           !gnm_expr_top_is_array_corner (corner->base.texpr)) {
+               g_warning ("Funky array setup.");
+               return handle_empty (NULL, flags);
+       }
+
+       gnm_cell_eval (corner);
+       a = gnm_expr_top_get_array_value (corner->base.texpr);
+       if (a == NULL)
+               return handle_empty (NULL, flags);
+
+       if ((VALUE_IS_CELLRANGE (a) || VALUE_IS_ARRAY (a))) {
+               int const num_x = value_area_get_width (a, pos);
+               int const num_y = value_area_get_height (a, pos);
+               int x = expr->array_elem.x;
+               int y = expr->array_elem.y;
+
+               /* Evaluate relative to the upper left corner */
+               GnmEvalPos tmp_ep = *pos;
+               tmp_ep.eval.col -= x;
+               tmp_ep.eval.row -= y;
+
+               /* If the src array is 1 element wide or tall we wrap */
+               if (x >= 1 && num_x == 1)
+                       x = 0;
+               if (y >= 1 && num_y == 1)
+                       y = 0;
+               if (x >= num_x || y >= num_y)
+                       return value_new_error_NA (pos);
+
+               a = (GnmValue *)value_area_get_x_y (a, x, y, &tmp_ep);
+       }
+
+       return handle_empty ((a != NULL) ? value_dup (a) : NULL, flags);
+}
+
 GnmValue *
 gnm_expr_top_eval (GnmExprTop const *texpr,
                   GnmEvalPos const *pos,
                   GnmExprEvalFlags flags)
 {
        GnmValue *res;
-       GnmEvalPos ep;
-       GnmExprArrayCorner array;
 
        g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), NULL);
 
        gnm_app_recalc_start ();
-       if ((flags & GNM_EXPR_EVAL_ARRAY_CONTEXT) && !pos->array) {
-               array.oper = GNM_EXPR_OP_ARRAY_CORNER;
-               array.cols = array.rows = 1;
-               array.value = NULL;
-               array.expr = texpr->expr;
-               ep = *pos;
-               ep.array = &array;
-               pos = &ep;
-       }
-       res = gnm_expr_eval (texpr->expr, pos, flags);
+
+       if (gnm_expr_top_is_array_corner (texpr))
+               res = gnm_expr_top_eval_array_corner (texpr, pos, flags);
+       else if (gnm_expr_top_is_array_elem (texpr, NULL, NULL))
+               res = gnm_expr_top_eval_array_elem (texpr, pos, flags);
+       else if ((flags & GNM_EXPR_EVAL_ARRAY_CONTEXT) && !eval_pos_is_array_context (pos)) {
+               // Array context out of the blue.  Fake it.
+               GnmEvalPos pos2;
+               GnmExprTop const *fake = gnm_expr_top_new_array_corner (1, 1, NULL);
+               ((GnmExpr *)(fake->expr))->array_corner.expr = texpr->expr; // Patch in our expr
+               pos2 = *pos;
+               pos2.array_texpr = fake;
+               res = gnm_expr_eval (texpr->expr, &pos2, flags);
+               ((GnmExpr *)(fake->expr))->array_corner.expr = NULL;
+               gnm_expr_top_unref (fake);
+       } else
+               res = gnm_expr_eval (texpr->expr, pos, flags);
        gnm_app_recalc_finish ();
 
        return res;
@@ -3217,11 +3260,7 @@ GnmCellRef const *
 gnm_expr_top_get_cellref (GnmExprTop const *texpr)
 {
        g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), NULL);
-
-       if (GNM_EXPR_GET_OPER (texpr->expr) != GNM_EXPR_OP_CELLREF)
-               return NULL;
-
-       return &texpr->expr->cellref.ref;
+       return gnm_expr_get_cellref (texpr->expr);
 }
 
 static GnmExpr const *
@@ -3311,21 +3350,6 @@ gnm_expr_top_is_rangeref (GnmExprTop const *texpr)
        return gnm_expr_is_rangeref (texpr->expr);
 }
 
-/**
- * gnm_expr_top_new_array_corner:
- * @expr: #GnmExprTop
- *
- * Returns: (transfer none): the #GnmExprArrayCorner or %NULL.
- **/
-GnmExprArrayCorner const *
-gnm_expr_top_get_array_corner (GnmExprTop const *texpr)
-{
-       g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), NULL);
-       return GNM_EXPR_GET_OPER (texpr->expr) == GNM_EXPR_OP_ARRAY_CORNER
-               ? &texpr->expr->array_corner
-               : NULL;
-}
-
 gboolean
 gnm_expr_top_is_array_corner (GnmExprTop const *texpr)
 {
@@ -3333,6 +3357,34 @@ gnm_expr_top_is_array_corner (GnmExprTop const *texpr)
        return GNM_EXPR_GET_OPER (texpr->expr) == GNM_EXPR_OP_ARRAY_CORNER;
 }
 
+void
+gnm_expr_top_get_array_size (GnmExprTop const *texpr, int *cols, int *rows)
+{
+       g_return_if_fail (GNM_IS_EXPR_TOP (texpr));
+       g_return_if_fail (GNM_EXPR_GET_OPER (texpr->expr) == GNM_EXPR_OP_ARRAY_CORNER);
+
+       if (cols)
+               *cols = texpr->expr->array_corner.cols;
+       if (rows)
+               *rows = texpr->expr->array_corner.rows;
+}
+
+GnmValue *
+gnm_expr_top_get_array_value (GnmExprTop const *texpr)
+{
+       g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), NULL);
+       g_return_val_if_fail (GNM_EXPR_GET_OPER (texpr->expr) == GNM_EXPR_OP_ARRAY_CORNER, NULL);
+       return texpr->expr->array_corner.value;
+}
+
+GnmExpr const *
+gnm_expr_top_get_array_expr (GnmExprTop const *texpr)
+{
+       g_return_val_if_fail (GNM_IS_EXPR_TOP (texpr), NULL);
+       g_return_val_if_fail (GNM_EXPR_GET_OPER (texpr->expr) == GNM_EXPR_OP_ARRAY_CORNER, NULL);
+       return texpr->expr->array_corner.expr;
+}
+
 gboolean
 gnm_expr_top_is_array_elem (GnmExprTop const *texpr, int *x, int *y)
 {
diff --git a/src/expr.h b/src/expr.h
index 1f7f38a..a66eea1 100644
--- a/src/expr.h
+++ b/src/expr.h
@@ -96,6 +96,8 @@ gboolean  gnm_expr_is_empty          (GnmExpr const *expr);
 
 GnmValue const *gnm_expr_get_constant  (GnmExpr const *expr);
 
+GnmCellRef const*gnm_expr_get_cellref  (GnmExpr const *expr);
+
 void     gnm_expr_as_gstring        (GnmExpr const *expr,
                                      GnmConventionsOut *out);
 char    *gnm_expr_as_string         (GnmExpr const *expr, GnmParsePos const *pp,
@@ -158,8 +160,10 @@ gboolean   gnm_expr_top_is_err             (GnmExprTop const *texpr, GnmStdError e);
 gboolean       gnm_expr_top_is_rangeref        (GnmExprTop const *texpr);
 gboolean       gnm_expr_top_is_array_elem      (GnmExprTop const *texpr, int *x, int *y);
 gboolean       gnm_expr_top_is_array_corner    (GnmExprTop const *texpr);
-GnmExprArrayCorner const *gnm_expr_top_get_array_corner (GnmExprTop const *texpr);
 gboolean       gnm_expr_top_is_array           (GnmExprTop const *texpr);
+void           gnm_expr_top_get_array_size     (GnmExprTop const *texpr, int *cols, int *rows);
+GnmValue       *gnm_expr_top_get_array_value   (GnmExprTop const *texpr);
+GnmExpr const  *gnm_expr_top_get_array_expr    (GnmExprTop const *texpr);
 GnmValue       *gnm_expr_top_get_range         (GnmExprTop const *texpr);
 GSList        *gnm_expr_top_get_ranges         (GnmExprTop const *texpr);
 GnmValue const *gnm_expr_top_get_constant      (GnmExprTop const *texpr);
diff --git a/src/func-builtin.c b/src/func-builtin.c
index 985432c..cbca75c 100644
--- a/src/func-builtin.c
+++ b/src/func-builtin.c
@@ -29,8 +29,8 @@
 #include <value.h>
 #include <selection.h>
 #include <expr.h>
-#include <expr-deriv.h>
 #include <expr-impl.h>
+#include <expr-deriv.h>
 #include <sheet.h>
 #include <cell.h>
 #include <application.h>
@@ -162,6 +162,7 @@ gnumeric_table_link (GnmFuncEvalInfo *ei, gboolean qlink)
 {
        GnmDependent *dep = ei->pos->dep;
        GnmRangeRef rr;
+       int cols, rows;
 
        if (!qlink)
                return DEPENDENT_NO_FLAG;
@@ -169,6 +170,8 @@ gnumeric_table_link (GnmFuncEvalInfo *ei, gboolean qlink)
        if (!eval_pos_is_array_context (ei->pos))
                return DEPENDENT_IGNORE_ARGS;
 
+       gnm_expr_top_get_array_size (ei->pos->array_texpr, &cols, &rows);
+
        rr.a.col_relative = rr.a.row_relative =
        rr.b.col_relative = rr.b.row_relative = FALSE;
        rr.a.sheet = rr.b.sheet = dep->sheet;
@@ -176,13 +179,13 @@ gnumeric_table_link (GnmFuncEvalInfo *ei, gboolean qlink)
        g_return_val_if_fail (ei->pos->eval.col > 0, DEPENDENT_IGNORE_ARGS);
        rr.a.col = rr.b.col = ei->pos->eval.col - 1;
        rr.a.row = ei->pos->eval.row;
-       rr.b.row = rr.a.row + ei->pos->array->rows - 1;
+       rr.b.row = rr.a.row + rows - 1;
        dependent_add_dynamic_dep (dep, &rr);
 
        g_return_val_if_fail (ei->pos->eval.row > 0, DEPENDENT_IGNORE_ARGS);
        rr.a.row = rr.b.row = ei->pos->eval.row - 1;
        rr.a.col = ei->pos->eval.col;
-       rr.b.col = rr.a.col + ei->pos->array->cols - 1;
+       rr.b.col = rr.a.col + cols - 1;
        dependent_add_dynamic_dep (dep, &rr);
 
        return DEPENDENT_IGNORE_ARGS;
@@ -196,6 +199,7 @@ gnumeric_table (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
        GnmCellPos     pos;
        GnmEvalPos const *ep = ei->pos;
        int x, y;
+       int cols, rows;
 
        /* evaluation clears the dynamic deps */
        gnumeric_table_link (ei, TRUE);
@@ -208,12 +212,12 @@ gnumeric_table (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
 
        for (x = 0; x < 2 ; x++) {
                GnmExpr const *arg = argv[x];
+               GnmCellRef const *cr = arg ? gnm_expr_get_cellref (arg) : NULL;
                in[x] = NULL;
                val[x] = NULL;
 
-               if (arg && GNM_EXPR_GET_OPER (arg) == GNM_EXPR_OP_CELLREF) {
-                       gnm_cellpos_init_cellref (&pos, &arg->cellref.ref,
-                                                 &ep->eval, ep->sheet);
+               if (cr) {
+                       gnm_cellpos_init_cellref (&pos, cr, &ep->eval, ep->sheet);
                        in[x] = sheet_cell_get (ep->sheet, pos.col, pos.row);
                        if (NULL == in[x])
                                in[x] = sheet_cell_fetch (ep->sheet, pos.col, pos.row);
@@ -238,8 +242,10 @@ gnumeric_table (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
                        val[2] = value_dup (in[2]->value);
        }
 
-       res = value_new_array (ep->array->cols, ep->array->rows);
-       for (x = ep->array->cols ; x-- > 0 ; ) {
+       gnm_expr_top_get_array_size (ei->pos->array_texpr, &cols, &rows);
+
+       res = value_new_array (cols, rows);
+       for (x = cols ; x-- > 0 ; ) {
                x_iter = sheet_cell_get (ep->sheet,
                        x + ep->eval.col, ep->eval.row-1);
                if (NULL == x_iter)
@@ -256,7 +262,7 @@ gnumeric_table (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
                        val[0] = value_dup (x_iter->value);
                }
 
-               for (y = ep->array->rows ; y-- > 0 ; ) {
+               for (y = rows ; y-- > 0 ; ) {
                        g_signal_emit_by_name (gnm_app_get_app (), "recalc-finished");
                        y_iter = sheet_cell_get (ep->sheet,
                                ep->eval.col-1, y + ep->eval.row);
diff --git a/src/func.c b/src/func.c
index 53ba25a..bcaba9c 100644
--- a/src/func.c
+++ b/src/func.c
@@ -1592,8 +1592,7 @@ function_iterate_argument_values (GnmEvalPos const        *ep,
                        val = gnm_expr_eval (expr, ep,
                                GNM_EXPR_EVAL_PERMIT_EMPTY | GNM_EXPR_EVAL_PERMIT_NON_SCALAR);
                else
-                       val = gnm_expr_eval (expr, ep,
-                               GNM_EXPR_EVAL_PERMIT_EMPTY);
+                       val = gnm_expr_eval (expr, ep, GNM_EXPR_EVAL_PERMIT_EMPTY);
 
                if (val == NULL)
                        continue;
@@ -1609,3 +1608,16 @@ function_iterate_argument_values (GnmEvalPos const       *ep,
        }
        return result;
 }
+
+
+GnmFunc const *
+gnm_eval_info_get_func (GnmFuncEvalInfo const *ei)
+{
+       return ei->func_call->func;
+}
+
+int
+gnm_eval_info_get_arg_count (GnmFuncEvalInfo const *ei)
+{
+       return ei->func_call->argc;
+}
diff --git a/src/func.h b/src/func.h
index 85fccc0..5936985 100644
--- a/src/func.h
+++ b/src/func.h
@@ -220,6 +220,10 @@ struct _GnmFuncEvalInfo {
        GnmExprEvalFlags flags;
 };
 
+GnmFunc const *gnm_eval_info_get_func (GnmFuncEvalInfo const *ei);
+int gnm_eval_info_get_arg_count (GnmFuncEvalInfo const *ei);
+
+
 GType       gnm_func_get_type        (void);
 void       gnm_func_free            (GnmFunc *func);
 GnmFunc           *gnm_func_ref             (GnmFunc *func);
diff --git a/src/position.c b/src/position.c
index 18329af..a5d0714 100644
--- a/src/position.c
+++ b/src/position.c
@@ -96,8 +96,8 @@ eval_pos_init (GnmEvalPos *ep, Sheet *sheet, int col, int row)
        ep->eval.col = col;
        ep->eval.row = row;
        ep->sheet = sheet;
-       ep->dep   = NULL;
-       ep->array = NULL;
+       ep->dep = NULL;
+       ep->array_texpr = NULL;
 
        return ep;
 }
@@ -117,10 +117,10 @@ eval_pos_init_pos (GnmEvalPos *ep, Sheet *sheet, GnmCellPos const *pos)
        g_return_val_if_fail (sheet != NULL, NULL);
        g_return_val_if_fail (pos != NULL, NULL);
 
-       ep->eval  = *pos;
+       ep->eval = *pos;
        ep->sheet = sheet;
-       ep->dep   = NULL;
-       ep->array = NULL;
+       ep->dep = NULL;
+       ep->array_texpr = NULL;
 
        return ep;
 }
@@ -141,7 +141,7 @@ eval_pos_init_dep (GnmEvalPos *ep, GnmDependent const *dep)
        ep->eval = *dependent_pos (dep);
        ep->sheet = dep->sheet;
        ep->dep = (GnmDependent *)dep;
-       ep->array = NULL;
+       ep->array_texpr = NULL;
 
        return ep;
 }
@@ -180,10 +180,10 @@ eval_pos_init_cell (GnmEvalPos *ep, GnmCell const *cell)
        g_return_val_if_fail (ep != NULL, NULL);
        g_return_val_if_fail (cell != NULL, NULL);
 
-       ep->eval  = cell->pos;
+       ep->eval = cell->pos;
        ep->sheet = cell->base.sheet;
-       ep->dep   = (GnmDependent *)GNM_CELL_TO_DEP (cell);
-       ep->array = NULL;
+       ep->dep = (GnmDependent *)GNM_CELL_TO_DEP (cell);
+       ep->array_texpr = NULL;
 
        return ep;
 }
@@ -205,12 +205,18 @@ eval_pos_init_sheet (GnmEvalPos *ep, Sheet const *sheet)
 
        ep->eval.col = ep->eval.row = 0;
        ep->sheet = (Sheet *)sheet;
-       ep->dep   = NULL;
-       ep->array = NULL;
+       ep->dep = NULL;
+       ep->array_texpr = NULL;
 
        return ep;
 }
 
+gboolean
+eval_pos_is_array_context (GnmEvalPos const *ep)
+{
+       return ep->array_texpr != NULL;
+}
+
 
 static GnmParsePos *
 gnm_parse_pos_dup (GnmParsePos *ep)
diff --git a/src/position.h b/src/position.h
index a02500c..26e7c34 100644
--- a/src/position.h
+++ b/src/position.h
@@ -9,10 +9,10 @@ G_BEGIN_DECLS
 GType gnm_cell_pos_get_type (void); /* boxed type */
 
 struct _GnmEvalPos {
-       GnmCellPos                eval;
-       Sheet                    *sheet;
-       GnmDependent             *dep;   /* optionally NULL */
-       GnmExprArrayCorner const *array; /* non-NULL if top level is array */
+       GnmCellPos eval;
+       Sheet *sheet;
+       GnmDependent *dep;       /* optionally NULL */
+       GnmExprTop const *array_texpr; /* non-NULL if top level is array */
 };
 
 struct _GnmParsePos {
@@ -35,7 +35,7 @@ GnmEvalPos  *eval_pos_init_dep           (GnmEvalPos *ep, GnmDependent const *dep);
 GnmEvalPos  *eval_pos_init_cell           (GnmEvalPos *ep, GnmCell const *cell);
 GnmEvalPos  *eval_pos_init_editpos (GnmEvalPos *ep, SheetView const *sv);
 GnmEvalPos  *eval_pos_init_sheet   (GnmEvalPos *ep, Sheet const *sheet);
-#define      eval_pos_is_array_context(ep) ((ep)->array != NULL)
+gboolean     eval_pos_is_array_context (GnmEvalPos const *ep);
 
 /* Initialization routines for Parse Positions */
 GType        gnm_parse_pos_get_type (void); /* Boxed type */
diff --git a/src/sheet-autofill.c b/src/sheet-autofill.c
index d0b1771..bc52432 100644
--- a/src/sheet-autofill.c
+++ b/src/sheet-autofill.c
@@ -18,7 +18,6 @@
 #include "workbook.h"
 #include "sheet-style.h"
 #include "expr.h"
-#include "expr-impl.h"
 #include "gnm-datetime.h"
 #include "mstyle.h"
 #include "ranges.h"
@@ -836,8 +835,6 @@ afc_set_cell_hint (AutoFiller *af, GnmCell *cell, GnmCellPos const *pos,
                GnmExprRelocateInfo rinfo;
                GnmExprTop const *texpr;
                GnmExprTop const *src_texpr = src->base.texpr;
-               GnmExprArrayCorner const *array =
-                       gnm_expr_top_get_array_corner (src_texpr);
                Sheet *sheet = src->base.sheet;
 
                /* Arrays are always assigned fully at the corner.  */
@@ -854,18 +851,21 @@ afc_set_cell_hint (AutoFiller *af, GnmCell *cell, GnmCellPos const *pos,
                texpr = gnm_expr_top_relocate (src_texpr, &rinfo, FALSE);
 
                /* Clip arrays that are only partially copied.  */
-               if (array) {
+               if (gnm_expr_top_is_array_corner (src_texpr)) {
                         GnmExpr const *aexpr;
-                       guint limit_x = afe->last.col - pos->col + 1;
-                       guint limit_y = afe->last.row - pos->row + 1;
-                        unsigned cols = MIN (limit_x, array->cols);
-                        unsigned rows = MIN (limit_y, array->rows);
+                       int limit_x = afe->last.col - pos->col + 1;
+                       int limit_y = afe->last.row - pos->row + 1;
+                        int cols, rows;
+
+                       gnm_expr_top_get_array_size (texpr, &cols, &rows);
+                        cols = MIN (limit_x, cols);
+                        rows = MIN (limit_y, rows);
 
                         if (texpr) {
-                                aexpr = gnm_expr_copy (texpr->expr->array_corner.expr);
+                                aexpr = gnm_expr_copy (gnm_expr_top_get_array_expr (texpr));
                                 gnm_expr_top_unref (texpr);
                         } else
-                                aexpr = gnm_expr_copy (array->expr);
+                                aexpr = gnm_expr_copy (gnm_expr_top_get_array_expr (src_texpr));
 
                        if (doit)
                                gnm_cell_set_array_formula
diff --git a/src/sheet.c b/src/sheet.c
index 56ab6f5..14b5f7a 100644
--- a/src/sheet.c
+++ b/src/sheet.c
@@ -52,7 +52,6 @@
 #include "sheet-private.h"
 #include "expr-name.h"
 #include "expr.h"
-#include "expr-impl.h"
 #include "rendered-value.h"
 #include "gnumeric-conf.h"
 #include "sheet-object-impl.h"
@@ -5911,7 +5910,6 @@ cb_sheet_cell_copy (G_GNUC_UNUSED gpointer unused, gpointer key, gpointer new_sh
        GnmCell const *cell = key;
        Sheet *dst = new_sheet_param;
        Sheet *src;
-       GnmExprArrayCorner const *array;
        GnmExprTop const *texpr;
 
        g_return_if_fail (dst != NULL);
@@ -5919,17 +5917,18 @@ cb_sheet_cell_copy (G_GNUC_UNUSED gpointer unused, gpointer key, gpointer new_sh
 
        src = cell->base.sheet;
        texpr = cell->base.texpr;
-       array = gnm_cell_is_array_corner (cell);
 
-       if (array) {
+       if (texpr && gnm_expr_top_is_array_corner (texpr)) {
+               int cols, rows;
+
                texpr = gnm_expr_top_relocate_sheet (texpr, src, dst);
-               array = gnm_expr_top_get_array_corner (texpr);
+               gnm_expr_top_get_array_size (texpr, &cols, &rows);
 
                gnm_cell_set_array_formula (dst,
                        cell->pos.col, cell->pos.row,
-                       cell->pos.col + array->cols-1,
-                       cell->pos.row + array->rows-1,
-                       gnm_expr_top_new (gnm_expr_copy (array->expr)));
+                       cell->pos.col + cols - 1,
+                       cell->pos.row + rows - 1,
+                       gnm_expr_top_new (gnm_expr_copy (gnm_expr_top_get_array_expr (texpr))));
 
                gnm_expr_top_unref (texpr);
        } else if (texpr && gnm_expr_top_is_array_elem (texpr, NULL, NULL)) {
diff --git a/src/style-conditions.c b/src/style-conditions.c
index f2663cd..cb93d99 100644
--- a/src/style-conditions.c
+++ b/src/style-conditions.c
@@ -369,13 +369,10 @@ gnm_style_cond_get_alternate_expr (GnmStyleCond const *cond)
 static gboolean
 isself (GnmExpr const *expr)
 {
-       GnmCellRef const *cr;
+       GnmCellRef const *cr = gnm_expr_get_cellref (expr);
 
-       if (GNM_EXPR_GET_OPER (expr) != GNM_EXPR_OP_CELLREF)
-               return FALSE;
-       cr = &expr->cellref.ref;
-
-       return (cr->sheet == NULL &&
+       return (cr &&
+               cr->sheet == NULL &&
                cr->col == 0 && cr->row == 0 &&
                cr->col_relative && cr->row_relative);
 }
diff --git a/src/wbc-gtk.c b/src/wbc-gtk.c
index 09488b6..3e6907f 100644
--- a/src/wbc-gtk.c
+++ b/src/wbc-gtk.c
@@ -44,7 +44,6 @@
 #include "style-font.h"
 #include "gnm-format.h"
 #include "expr.h"
-#include "expr-impl.h"
 #include "style-color.h"
 #include "style-border.h"
 #include "gnumeric-conf.h"
@@ -2233,10 +2232,7 @@ cb_workbook_debug_info (WBCGtk *wbcg)
 
        if (gnm_debug_flag ("expr-sharer")) {
                GnmExprSharer *es = workbook_share_expressions (wb, FALSE);
-
-               g_printerr ("Expression sharer results:\n"
-                           "Nodes in: %d, nodes stored: %d, nodes killed: %d.\n",
-                           es->nodes_in, es->nodes_stored, es->nodes_killed);
+               gnm_expr_sharer_report (es);
                gnm_expr_sharer_destroy (es);
        }
 
diff --git a/src/widgets/gnm-validation-combo-view.c b/src/widgets/gnm-validation-combo-view.c
index 1ab2cb9..40c2c1a 100644
--- a/src/widgets/gnm-validation-combo-view.c
+++ b/src/widgets/gnm-validation-combo-view.c
@@ -35,7 +35,6 @@
 #include "sheet-view.h"
 #include "sheet.h"
 #include "cell.h"
-#include "expr-impl.h"
 #include "expr.h"
 #include "value.h"
 
diff --git a/src/workbook-view.c b/src/workbook-view.c
index d9ba25c..518a710 100644
--- a/src/workbook-view.c
+++ b/src/workbook-view.c
@@ -34,7 +34,6 @@
 #include "func.h"
 #include "expr.h"
 #include "expr-name.h"
-#include "expr-impl.h"
 #include "value.h"
 #include "ranges.h"
 #include "selection.h"
@@ -469,14 +468,15 @@ wb_view_edit_line_set (WorkbookView *wbv, WorkbookControl *optional_wbc)
                                }
 
                                if (corner) {
-                                       GnmExprArrayCorner const *ac = gnm_cell_is_array_corner (corner);
+                                       int cols, rows;
+                                       char *tmp;
 
-                                       char *tmp = g_strdup_printf
+                                       gnm_expr_top_get_array_size (corner->base.texpr, &cols, &rows);
+
+                                       tmp = g_strdup_printf
                                                ("{%s}(%d%c%d)[%d][%d]",
                                                 text,
-                                                ac->cols,
-                                                go_locale_get_arg_sep (),
-                                                ac->rows,
+                                                cols, go_locale_get_arg_sep (), rows,
                                                 x, y);
                                        g_free (text);
                                        text = tmp;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]