[gnumeric] Calculation: support volatile functions.



commit c4c01aa9b2c9830d068060c44ce560a9e98c22aa
Author: Morten Welinder <terra gnome org>
Date:   Wed Mar 5 14:45:28 2014 -0500

    Calculation: support volatile functions.
    
    This comes down to recomputing RAND, TODAY, etc. on load, even from formats
    that contain computed values.

 ChangeLog           |    8 ++++++++
 NEWS                |    3 +++
 src/dependent.c     |   18 ++++++++++++++++++
 src/dependent.h     |    3 +++
 src/expr.c          |   29 +++++++++++++++++++++++++++++
 src/expr.h          |    1 +
 src/workbook-view.c |    1 +
 7 files changed, 63 insertions(+), 0 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index a306228..7aefad0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2014-03-05  Morten Welinder  <terra gnome org>
 
+       * src/expr.c (gnm_expr_top_is_volatile): New function.
+
+       * src/workbook-view.c (workbook_view_new_from_input): Queue all
+       volatile expressions.
+
+       * src/dependent.c (workbook_queue_volatile_recalc): New function.
+       (dependent_is_volatile): New function.
+
        * src/sheet.c (sheet_range_set_expr_cb, sheet_range_set_text):
        Don't set the initial range here.
 
diff --git a/NEWS b/NEWS
index ef8ca16..e166d8e 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,8 @@
 Gnumeric 1.12.13
 
+Morten:
+       * Support volatile functions.  [#305798]
+
 --------------------------------------------------------------------------
 Gnumeric 1.12.12
 
diff --git a/src/dependent.c b/src/dependent.c
index ab9b974..e89971f 100644
--- a/src/dependent.c
+++ b/src/dependent.c
@@ -2814,6 +2814,16 @@ workbook_queue_all_recalc (Workbook *wb)
        WORKBOOK_FOREACH_DEPENDENT (wb, dep, dependent_flag_recalc (dep););
 }
 
+void
+workbook_queue_volatile_recalc (Workbook *wb)
+{
+       WORKBOOK_FOREACH_DEPENDENT (wb, dep, {
+               if (dependent_is_volatile (dep))        
+                       dependent_flag_recalc (dep);
+       });
+}
+
+
 /**
  * workbook_recalc :
  * @wb:
@@ -2905,6 +2915,14 @@ dynamic_dep_free (DynamicDep *dyn)
        g_free (dyn);
 }
 
+
+gboolean
+dependent_is_volatile (GnmDependent *dep)
+{
+       /* This might need to be a virtual call. */
+       return dep->texpr && gnm_expr_top_is_volatile (dep->texpr);
+}
+
 /**
  * gnm_dep_container_new: (skip)
  * @sheet: #Sheet
diff --git a/src/dependent.h b/src/dependent.h
index aedfcee..a4b8b68 100644
--- a/src/dependent.h
+++ b/src/dependent.h
@@ -96,6 +96,8 @@ void   dependent_unlink          (GnmDependent *dep);
 void    dependent_queue_recalc    (GnmDependent *dep);
 void    dependent_add_dynamic_dep (GnmDependent *dep, GnmRangeRef const *rr);
 
+gboolean dependent_is_volatile     (GnmDependent *dep);
+
 GnmCellPos const *dependent_pos (GnmDependent const *dep);
 
 GOUndo  *dependents_relocate       (GnmExprRelocateInfo const *info);
@@ -110,6 +112,7 @@ void dependents_invalidate_sheet  (Sheet *sheet, gboolean destroy);
 void dependents_workbook_destroy  (Workbook *wb);
 void dependents_revive_sheet      (Sheet *sheet);
 void workbook_queue_all_recalc   (Workbook *wb);
+void workbook_queue_volatile_recalc (Workbook *wb);
 
 void gnm_dep_style_dependency (Sheet *sheet,
                               GnmExprTop const *texpr,
diff --git a/src/expr.c b/src/expr.c
index e6395a3..0e9bef8 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -3059,6 +3059,35 @@ gnm_expr_top_contains_subtotal (GnmExprTop const *texpr)
        return gnm_expr_contains_subtotal (texpr->expr);
 }
 
+static GnmExpr const *
+cb_is_volatile (GnmExpr const *expr, GnmExprWalk *data)
+{
+       gboolean *res = data->user;
+       if (GNM_EXPR_GET_OPER (expr) == GNM_EXPR_OP_FUNCALL &&
+           (expr->func.func->flags & GNM_FUNC_VOLATILE)) {
+               *res = TRUE;
+               data->stop = TRUE;
+       }
+       return NULL;
+}
+
+gboolean
+gnm_expr_top_is_volatile (GnmExprTop const *texpr)
+{
+       gboolean res = FALSE;
+
+       /*
+        * An expression is volatile if it contains a call to a volatile
+        * function, even in cases like IF(TRUE,12,RAND()) where the
+        * volatile function won't even be reached.
+        */
+
+       g_return_val_if_fail (IS_GNM_EXPR_TOP (texpr), FALSE);
+       gnm_expr_walk (texpr->expr, cb_is_volatile, &res);
+       return res;
+}
+
+
 GnmValue *
 gnm_expr_top_eval (GnmExprTop const *texpr,
                   GnmEvalPos const *pos,
diff --git a/src/expr.h b/src/expr.h
index 610339a..9846298 100644
--- a/src/expr.h
+++ b/src/expr.h
@@ -166,6 +166,7 @@ void                gnm_expr_top_get_boundingbox    (GnmExprTop const *texpr,
                                                 Sheet const *sheet,
                                                 GnmRange *bound);
 gboolean       gnm_expr_top_contains_subtotal  (GnmExprTop const *texpr);
+gboolean       gnm_expr_top_is_volatile        (GnmExprTop const *texpr);
 GSList        *gnm_expr_top_referenced_sheets  (GnmExprTop const *texpr);
 GnmExpr const  *gnm_expr_top_first_funcall     (GnmExprTop const *texpr);
 GnmExprTop const *gnm_expr_top_transpose        (GnmExprTop const *texpr);
diff --git a/src/workbook-view.c b/src/workbook-view.c
index bb315cf..3dc4de1 100644
--- a/src/workbook-view.c
+++ b/src/workbook-view.c
@@ -1293,6 +1293,7 @@ workbook_view_new_from_input (GsfInput *input,
                } else {
                        workbook_share_expressions (new_wb, TRUE);
                        workbook_optimize_style (new_wb);
+                       workbook_queue_volatile_recalc (new_wb);
                        workbook_recalc (new_wb);
                        go_doc_set_dirty (GO_DOC (new_wb), FALSE);
                        if (optional_uri && workbook_get_file_exporter (new_wb))


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