Grob::internal_get_pure_property (SCM sym, int start, int end) const
{
SCM val = internal_get_property_data (sym);
- if (ly_is_procedure (val) || is_unpure_pure_container (val))
+ if (ly_is_procedure (val))
return call_pure_function (val, scm_list_1 (self_scm ()), start, end);
+
+ if (is_unpure_pure_container (val)) {
+ // Do cache, if the function ignores 'start' and 'end'
+ if (is_unchanging_unpure_pure_container (val))
+ return internal_get_property (sym);
+ else
+ return call_pure_function (val, scm_list_1 (self_scm ()), start, end);
+ }
+
if (is_simple_closure (val))
return evaluate_with_simple_closure (self_scm (),
simple_closure_expression (val),
#include "lily-guile.hh"
bool is_unpure_pure_container (SCM s);
+bool is_unchanging_unpure_pure_container (SCM s);
SCM unpure_pure_container_unpure_part (SCM smob);
SCM unpure_pure_container_pure_part (SCM smob);
SCM ly_make_unpure_pure_container (SCM, SCM);
return (SCM_NIMP (s) && SCM_CELL_TYPE (s) == unpure_pure_container_tag);
}
+bool
+is_unchanging_unpure_pure_container (SCM s)
+// A container that has the same callback for both 'pure' and 'unpure' lookups
+// and which ignores the 'start' and 'end' columnns.
+// Such a callback will give the same answer for tentative or final layouts.
+{
+ LY_ASSERT_TYPE (is_unpure_pure_container, s, 1);
+ SCM pure_part = SCM_SMOB_OBJECT_2 (s);
+ return (SCM_UNBNDP (pure_part));
+}
+
SCM
unpure_pure_container_unpure_part (SCM smob)
{