+bool
+typecheck_grob (SCM symbol, SCM value)
+{
+ if (is_unpure_pure_container (value))
+ return typecheck_grob (symbol, unpure_pure_container_unpure_part (value))
+ && typecheck_grob (symbol, unpure_pure_container_pure_part (value));
+ return ly_is_procedure (value)
+ || is_simple_closure (value)
+ || type_check_assignment (symbol, value, ly_symbol2scm ("backend-type?"));
+}
+
+class Grob_properties
+{
+ friend class Grob_property_info;
+ friend SCM ly_make_grob_properties (SCM);
+ // alist_ may contain unexpanded nested overrides
+ SCM alist_;
+ // based_on_ is the cooked_ value from the next higher context that
+ // alist_ is based on
+ SCM based_on_;
+ // cooked_ is a version of alist_ where nested overrides have been
+ // expanded
+ SCM cooked_;
+ // cooked_from_ is the value of alist_ from which the expansion has
+ // been done
+ SCM cooked_from_;
+ // nested_ is a count of nested overrides in alist_
+ int nested_;
+
+ Grob_properties (SCM alist, SCM based_on) :
+ alist_ (alist), based_on_ (based_on),
+ // if the constructor was called with lists possibly containing
+ // partial overrides, we would need to initialize with based_on in
+ // order to trigger an initial update. But this should never
+ // happen, so we initialize straight with alist.
+ cooked_ (alist), cooked_from_ (alist), nested_ (0) { }
+ DECLARE_SIMPLE_SMOBS (Grob_properties);
+};
+
+#include "ly-smobs.icc"
+IMPLEMENT_SIMPLE_SMOBS (Grob_properties);
+IMPLEMENT_DEFAULT_EQUAL_P (Grob_properties);
+IMPLEMENT_TYPE_P (Grob_properties, "ly:grob-properties?");
+