+2006-09-24 Joe Neeman <joeneeman@gmail.com>
+ * lily/grob-property.cc: add scm debugging hooks into
+ property modification
+
+ * lily/context-property.cc:
+ * lily/engraver.cc:
+ rename make_foo_from_properties to internal_make_foo and
+ move it from context-property.cc to a member function of
+ Engraver.
+
+ * lily/include/lily-guile-macros.hh:
+ overload ly_symbol2scm macro so that there is no more need
+ to use internal_foo
+
+ * lily/volta-repeat-iterator.cc:
+ * lily/tweak-engraver.cc:
+ * lily/tuplet-bracket.cc:
+ * lily/span-bar-engraver.cc:
+ * lily/script-engraver.cc:
+ * lily/prob-scheme.cc:
+ * lily/pointer-group-interface.cc:
+ * lily/parser.yy:
+ * lily/grob-scheme.cc:
+ * lily/grob-property.cc:
+ * lily/context.cc:
+ * lily/context-property.cc:
+ * lily/break-substitution.cc:
+ * lily/break-align-engraver.cc:
+ * lily/axis-group-interface.cc:
+ * lily/align-interface.cc:
+ remove calls to internal_FOO
+
+ * lily/system-start-delimiter-engraver.cc:
+ * lily/parenthesis-engraver.cc:
+ * lily/accidental-engraver.cc:
+ remove calls to make_foo_from_properties
+
2006-09-23 Graham Percival <gpermus@gmail.com>
* Documentation/user/programming-iterfaces.itely: fix
level, so that we get the property settings for
Accidental from the respective Voice.
*/
- Grob *a
- = make_grob_from_properties (trans,
- ly_symbol2scm ("Accidental"),
- note_head->self_scm (),
- "Accidental");
+ Grob *a = trans->make_item ("Accidental", note_head->self_scm ());
/*
We add the accidentals to the support of the arpeggio,
Engraver *trans)
{
(void) note;
- Grob *a
- = make_grob_from_properties (trans,
- ly_symbol2scm ("AccidentalSuggestion"),
- note_head->self_scm (),
- "AccidentalSuggestion");
+ Grob *a = trans->make_item ("AccidentalSuggestion", note_head->self_scm ());
Side_position_interface::add_support (a, note_head);
if (Grob *stem = unsmob_grob (a->get_object ("stem")))
SCM sym = axis_offset_symbol (a);
SCM proc = axis_parent_positioning (a);
- element->internal_set_property (sym, proc);
+ element->set_property (sym, proc);
Axis_group_interface::add_element (me, element);
}
if (!e->get_parent (a))
e->set_parent (me, a);
- e->internal_set_object ((a == X_AXIS)
- ? ly_symbol2scm ("axis-group-parent-X")
- : ly_symbol2scm ("axis-group-parent-Y"),
- me->self_scm ());
+ e->set_object ((a == X_AXIS)
+ ? ly_symbol2scm ("axis-group-parent-X")
+ : ly_symbol2scm ("axis-group-parent-Y"),
+ me->self_scm ());
}
/* must be ordered, because Align_interface also uses
/*
Make left edge appear to come from same context as clef/bar-line etc.
*/
- left_edge_ = make_item_from_properties (random_source,
- ly_symbol2scm ("LeftEdge"),
- SCM_EOL,
- "LeftEdge");
+ left_edge_ = random_source->make_item ("LeftEdge", SCM_EOL);
add_to_group (left_edge_->get_property ("break-align-symbol"),
left_edge_);
}
if (!unsmob_grob_array (newval))
{
newval = Grob_array::make_array ();
- sc->internal_set_object (sym, newval);
+ sc->set_object (sym, newval);
}
Grob_array *new_array = unsmob_grob_array (newval);
if (!unsmob_grob_array (newval))
{
newval = Grob_array::make_array ();
- sc->internal_set_object (sym, newval);
+ sc->set_object (sym, newval);
}
substitute_grob_array (grob_array, unsmob_grob_array (newval));
}
else
{
SCM newval = do_break_substitution (val);
- sc->internal_set_object (sym, newval);
+ sc->set_object (sym, newval);
}
}
}
{
SCM base = updated_grob_properties (context, context_property);
current_context_val = scm_cons (base, base);
- context->internal_set_property (context_property, current_context_val);
+ context->set_property (context_property, current_context_val);
}
if (!scm_is_pair (current_context_val))
if (new_alist == daddy)
context->unset_property (context_property);
else
- context->internal_set_property (context_property, scm_cons (new_alist, daddy));
+ context->set_property (context_property, scm_cons (new_alist, daddy));
}
}
execute_general_pushpop_property (tg, context_prop, grob_prop_path, val);
}
else if (type == ly_symbol2scm ("assign"))
- tg->internal_set_property (scm_car (entry), scm_cadr (entry));
+ tg->set_property (scm_car (entry), scm_cadr (entry));
}
}
return copy;
}
}
-
-Grob *
-make_grob_from_properties (Engraver *tr, SCM symbol, SCM cause, char const *name)
-{
- Context *context = tr->context ();
-
- SCM props = updated_grob_properties (context, symbol);
-
- Object_key const *key = context->get_grob_key (name);
- Grob *grob = 0;
-
- SCM handle = scm_sloppy_assq (ly_symbol2scm ("meta"), props);
- SCM klass = scm_cdr (scm_sloppy_assq (ly_symbol2scm ("class"), scm_cdr (handle)));
-
- if (klass == ly_symbol2scm ("Item"))
- grob = new Item (props, key);
- else if (klass == ly_symbol2scm ("Spanner"))
- grob = new Spanner (props, key);
- else if (klass == ly_symbol2scm ("Paper_column"))
- grob = new Paper_column (props, key);
-
- assert (grob);
- dynamic_cast<Engraver *> (tr)->announce_grob (grob, cause);
-
- return grob;
-}
-
-Item *
-make_item_from_properties (Engraver *tr, SCM x, SCM cause, char const *name)
-{
- Item *it = dynamic_cast<Item *> (make_grob_from_properties (tr, x, cause, name));
- assert (it);
- return it;
-}
-
-Paper_column *
-make_paper_column_from_properties (Engraver *tr, SCM x, char const *name)
-{
- return dynamic_cast<Paper_column *> (make_grob_from_properties (tr, x, SCM_EOL, name));
-}
-
-Spanner *
-make_spanner_from_properties (Engraver *tr, SCM x, SCM cause, char const *name)
-{
- Spanner *sp = dynamic_cast<Spanner *> (make_grob_from_properties (tr, x, cause, name));
- assert (sp);
- return sp;
-}
SCM_ASSERT_TYPE (tr, context, SCM_ARG1, __FUNCTION__, "Context");
SCM_ASSERT_TYPE (scm_is_symbol (name), name, SCM_ARG2, __FUNCTION__, "symbol");
- tr->internal_set_property (name, val);
+ tr->set_property (name, val);
return SCM_UNSPECIFIED;
}
if (val != SCM_EOL)
ok = type_check_assignment (sym, val, ly_symbol2scm ("translation-type?"));
if (ok)
- internal_set_property (sym, val);
+ set_property (sym, val);
}
}
Stream_event *e = new Stream_event (type, origin);
for (int i = 0; props[i]; i += 2)
{
- e->internal_set_property (props[i], props[i+1]);
+ e->set_property (props[i], props[i+1]);
}
event_source_->broadcast (e);
e->unprotect ();
}
void
-Context::internal_set_property (SCM sym, SCM val)
-{
#ifndef NDEBUG
+Context::internal_set_property (SCM sym, SCM val, char const *file, int line, char const *fun)
+{
if (do_internal_type_checking_global)
assert (type_check_assignment (sym, val, ly_symbol2scm ("translation-type?")));
+#else
+Context::internal_set_property (SCM sym, SCM val)
+{
#endif
properties_dict ()->set (sym, val);
void
set_context_property_on_children (Context *trans, SCM sym, SCM val)
{
- trans->internal_set_property (sym, ly_deep_copy (val));
+ trans->set_property (sym, ly_deep_copy (val));
for (SCM p = trans->children_contexts (); scm_is_pair (p); p = scm_cdr (p))
{
Context *trg = unsmob_context (scm_car (p));
#include "engraver.hh"
#include "context.hh"
+#include "international.hh"
#include "item.hh"
#include "lilypond-key.hh"
#include "music.hh"
+#include "paper-column.hh"
#include "score-engraver.hh"
#include "spanner.hh"
#include "stream-event.hh"
{
}
+#ifndef NDEBUG
+static SCM creation_callback = SCM_EOL;
+LY_DEFINE (ly_set_grob_creation_callback, "ly:set-grob-creation-callback",
+ 1, 0, 0, (SCM cb),
+ "Specify a procedure that will be called every time a new grob "
+ "is created. The callback will receive as arguments the grob "
+ "that was created, the name of the C++ source file that caused "
+ "the grob to be created and the corresponding line number in the "
+ "C++ source file.")
+{
+ if (!ly_is_procedure (cb))
+ warning (_ ("not setting creation callback: not a procedure"));
+ else
+ creation_callback = cb;
+
+ return SCM_EOL;
+}
+#endif
+
+Grob *
+Engraver::internal_make_grob (SCM symbol, SCM cause, char const *name, char const *file, int line, char const *fun)
+{
+ SCM props = updated_grob_properties (context (), symbol);
+
+ Object_key const *key = context ()->get_grob_key (name);
+ Grob *grob = 0;
+
+ SCM handle = scm_sloppy_assq (ly_symbol2scm ("meta"), props);
+ SCM klass = scm_cdr (scm_sloppy_assq (ly_symbol2scm ("class"), scm_cdr (handle)));
+
+ if (klass == ly_symbol2scm ("Item"))
+ grob = new Item (props, key);
+ else if (klass == ly_symbol2scm ("Spanner"))
+ grob = new Spanner (props, key);
+ else if (klass == ly_symbol2scm ("Paper_column"))
+ grob = new Paper_column (props, key);
+
+ assert (grob);
+ announce_grob (grob, cause);
+
+#ifndef NDEBUG
+ if (ly_is_procedure (creation_callback))
+ scm_apply_0 (creation_callback,
+ scm_list_n (grob->self_scm (), scm_makfrom0str (file),
+ scm_from_int (line), scm_makfrom0str (fun), SCM_UNDEFINED));
+#endif
+
+ return grob;
+}
+
+Item *
+Engraver::internal_make_item (SCM x, SCM cause, char const *name, char const *file, int line, char const *fun)
+{
+ Item *it = dynamic_cast<Item *> (internal_make_grob (x, cause, name, file, line, fun));
+ assert (it);
+ return it;
+}
+
+Paper_column *
+Engraver::internal_make_column (SCM x, char const *name, char const *file, int line, char const *fun)
+{
+ return dynamic_cast<Paper_column *> (internal_make_grob (x, SCM_EOL, name, file, line, fun));
+}
+
+Spanner *
+Engraver::internal_make_spanner (SCM x, SCM cause, char const *name, char const *file, int line, char const *fun)
+{
+ Spanner *sp = dynamic_cast<Spanner *> (internal_make_grob (x, cause, name, file, line, fun));
+ assert (sp);
+ return sp;
+}
+
#include "translator.icc"
ADD_TRANSLATOR (Engraver,
&& !ly_is_procedure (data)
&& !is_simple_closure (data))
{
- g->internal_set_property (axis_offset_symbol (a),
- proc);
+ g->set_property (axis_offset_symbol (a), proc);
return ;
}
proc = ly_make_simple_closure (scm_list_1 (proc));
SCM expr = scm_list_3 (plus, proc, data);
- g->internal_set_property (axis_offset_symbol (a),
- ly_make_simple_closure (expr));
+ g->set_property (axis_offset_symbol (a), ly_make_simple_closure (expr));
}
data = scm_from_int (0);
SCM expr = scm_list_2 (proc, data);
- g->internal_set_property (axis_offset_symbol (a),
-
- // twice: one as a wrapper for grob property routines,
- // once for the actual delayed binding.
- ly_make_simple_closure (ly_make_simple_closure (expr)));
+ g->set_property (axis_offset_symbol (a),
+
+ // twice: one as a wrapper for grob property routines,
+ // once for the actual delayed binding.
+ ly_make_simple_closure (ly_make_simple_closure (expr)));
}
#include "paper-score.hh"
#include "output-def.hh"
#include "spanner.hh"
+#include "international.hh"
#include "item.hh"
#include "misc.hh"
#include "item.hh"
#include "program-option.hh"
#include "profile.hh"
#include "simple-closure.hh"
+#include "warn.hh"
+
+#ifndef NDEBUG
+static SCM modification_callback = SCM_EOL;
+
+LY_DEFINE (ly_set_grob_modification_callback, "ly:set-grob-modification-callback",
+ 1, 0, 0, (SCM cb),
+ "Specify a procedure that will be called every time lilypond modifies "
+ "a grob property. The callback will receive as arguments "
+ "the grob that is being modified, the name of the C++ file in which "
+ "the modification was requested, the line number in the C++ file in "
+ "which the modification was requested, the property to be changed and "
+ "the new value for the property.")
+{
+ if (!ly_is_procedure (cb))
+ warning (_ ("not setting modification callback: not a procedure"));
+ else
+ modification_callback = cb;
+ return SCM_EOL;
+}
+#endif
SCM
Grob::get_property_alist_chain (SCM def) const
extern void check_interfaces_for_property (Grob const *me, SCM sym);
void
-Grob::internal_set_property (SCM sym, SCM v)
-{
#ifndef NDEBUG
+Grob::internal_set_property (SCM sym, SCM v, char const *file, int line, char const *fun)
+{
SCM grob_p = ly_lily_module_constant ("ly:grob?");
SCM grob_list_p = ly_lily_module_constant ("grob-list?");
SCM type = scm_object_property (sym, ly_symbol2scm ("backend-type?"));
scm_display (scm_list_2 (sym, type), scm_current_output_port ());
assert (0);
}
+#else
+Grob::internal_set_property (SCM sym, SCM v)
+{
#endif
/* Perhaps we simply do the assq_set, but what the heck. */
check_interfaces_for_property (this, sym);
}
+#ifndef NDEBUG
+ if (ly_is_procedure (modification_callback))
+ scm_apply_0 (modification_callback,
+ scm_list_n (self_scm (),
+ scm_makfrom0str (file),
+ scm_from_int (line),
+ scm_makfrom0str (fun),
+ sym, v, SCM_UNDEFINED));
+#endif
+
mutable_property_alist_ = scm_assq_set_x (mutable_property_alist_, sym, v);
}
mutable_property_alist_ = scm_assq_remove_x (mutable_property_alist_, marker);
}
else
- internal_set_property (sym, value);
+ set_property (sym, value);
return value;
}
}
void
-Grob::del_property (SCM sym)
+Grob::internal_del_property (SCM sym)
{
mutable_property_alist_ = scm_assq_remove_x (mutable_property_alist_, sym);
}
&& !type_check_assignment (sym, val, ly_symbol2scm ("backend-type?")))
error ("typecheck failed");
- sc->internal_set_property (sym, val);
+ sc->set_property (sym, val);
return SCM_UNSPECIFIED;
}
/* properties: */
SCM internal_get_property (SCM name_sym) const;
SCM properties_as_alist () const;
- void internal_set_property (SCM var_sym, SCM value);
Context *where_defined (SCM name_sym, SCM *value) const;
void unset_property (SCM var_sym);
+#ifndef NDEBUG
+ void internal_set_property (SCM var_sym, SCM value, char const *file, int line, char const *fun);
+#else
+ void internal_set_property (SCM var_sym, SCM value);
+#endif
+
Context *create_context (Context_def *, string, SCM);
DECLARE_LISTENER (create_context_from_event);
DECLARE_LISTENER (acknowledge_infant);
*/
class Engraver : public Translator
{
+ Grob *internal_make_grob (SCM sym, SCM cause, char const *name,
+ char const *f, int l, char const *fun);
friend class Engraver_group;
protected:
void announce_grob (Grob *, SCM cause);
void announce_end_grob (Grob *, SCM cause);
+ Item *internal_make_item (SCM sym, SCM cause, char const *name,
+ char const *f, int l, char const *fun);
+ Spanner *internal_make_spanner (SCM sym, SCM cause, char const *name,
+ char const *f, int l, char const *fun);
+ Paper_column *internal_make_column (SCM sym, char const *name,
+ char const *f, int l, char const *fun);
+
/**
override other ctor
*/
TRANSLATOR_DECLARATIONS (Engraver);
};
-#define make_item(x, cause) make_item_from_properties (this, ly_symbol2scm (x), cause, x)
-#define make_spanner(x, cause) make_spanner_from_properties (this, ly_symbol2scm (x), cause, x)
-#define make_paper_column(x) make_paper_column_from_properties (this, ly_symbol2scm (x), x)
-Grob *make_grob_from_properties (Engraver *tr, SCM symbol, SCM cause, char const *name);
-Item *make_item_from_properties (Engraver *tg, SCM x, SCM cause, char const *name);
-Spanner *make_spanner_from_properties (Engraver *tg, SCM x, SCM cause, char const *name);
-Paper_column *make_paper_column_from_properties (Engraver *tg, SCM x, char const *name);
+#define make_item(x, cause) internal_make_item (ly_symbol2scm (x), cause, x, __FILE__, __LINE__, __FUNCTION__)
+#define make_spanner(x, cause) internal_make_spanner (ly_symbol2scm (x), cause, x, __FILE__, __LINE__, __FUNCTION__)
+#define make_paper_column(x) internal_make_column (ly_symbol2scm (x), x, __FILE__, __LINE__, __FUNCTION__)
+
#endif // ENGRAVER_HH
SCM internal_get_property (SCM symbol) const;
SCM get_property_data (SCM symbol) const;
SCM internal_get_object (SCM symbol) const;
- void del_property (SCM symbol);
- void internal_set_property (SCM sym, SCM val);
void internal_set_object (SCM sym, SCM val);
+ void internal_del_property (SCM symbol);
+
+#ifndef NDEBUG
+ void internal_set_property (SCM sym, SCM val, char const *file, int line, char const *fun);
+#else
+ void internal_set_property (SCM sym, SCM val);
+#endif
/* messages */
void warning (string) const;
SCM axis_offset_symbol (Axis a);
SCM axis_parent_positioning (Axis a);
-
#endif /* GROB_HH */
#ifdef CACHE_SYMBOLS
+/* this lets us "overload" macros such as get_property to take
+ symbols as well as strings */
+inline SCM
+scm_or_str2symbol (char const *c) { return scm_str2symbol (c); }
+
+inline SCM
+scm_or_str2symbol (SCM s) { return s; }
+
/* Using this trick we cache the value of scm_str2symbol ("fooo") where
"fooo" is a constant string. This is done at the cost of one static
variable per ly_symbol2scm() use, and one boolean evaluation for
if (__builtin_constant_p ((x))) \
{ \
if (!cached) \
- value = cached = scm_gc_protect_object (scm_str2symbol ((x))); \
+ value = cached = scm_gc_protect_object (scm_or_str2symbol (x)); \
} \
else \
- value = scm_str2symbol ((char *) (x)); \
+ value = scm_or_str2symbol (x); \
value; \
})
#else
#define get_property(x) internal_get_property (ly_symbol2scm (x))
#define get_object(x) internal_get_object (ly_symbol2scm (x))
-#define set_property(x, y) internal_set_property (ly_symbol2scm (x), y)
#define set_object(x, y) internal_set_object (ly_symbol2scm (x), y)
+#define del_property(x) internal_del_property (ly_symbol2scm (x))
+
+#ifndef NDEBUG
+#define set_property(x, y) internal_set_property (ly_symbol2scm (x), y, __FILE__, __LINE__, __FUNCTION__)
+#else
+#define set_property(x, y) internal_set_property (ly_symbol2scm (x), y)
+#endif
#endif /* LILY_GUILE_MACROS_HH */
SCM type () const { return type_; }
SCM get_property_alist (bool mutble) const;
SCM internal_get_property (SCM sym) const;
+
+#ifndef NDEBUG
+ void internal_set_property (SCM sym, SCM val, const char *file, int line, char const *fun);
+#else
void internal_set_property (SCM sym, SCM val);
+#endif
};
DECLARE_UNSMOB(Prob,prob);
SCM ly_prob_set_property_x (SCM system, SCM sym, SCM value);
if (Item *victim = dynamic_cast<Item*> (info.grob ()))
{
Engraver *eng = dynamic_cast<Engraver*> (info.origin_translator ());
- Item *paren = make_item_from_properties (eng,
- ly_symbol2scm ("ParenthesesItem"),
- victim->self_scm (),
- "ParenthesesItem");
+ Item *paren = eng->make_item ("ParenthesesItem", victim->self_scm ());
Pointer_group_interface::add_grob (paren, ly_symbol2scm ("elements"), victim);
set_music_properties (Music *p, SCM a)
{
for (SCM k = a; scm_is_pair (k); k = scm_cdr (k))
- p->internal_set_property (scm_caar (k), scm_cdar (k));
+ p->set_property (scm_caar (k), scm_cdar (k));
}
{
scm_arr = Grob_array::make_array ();
arr = unsmob_grob_array (scm_arr);
- me->internal_set_object (sym, scm_arr);
+ me->set_object (sym, scm_arr);
}
return arr;
}
SCM_ASSERT_TYPE (ps, obj, SCM_ARG1, __FUNCTION__, "Prob");
SCM_ASSERT_TYPE (scm_is_symbol (sym), sym, SCM_ARG2, __FUNCTION__, "symbol");
- ps->internal_set_property (sym, value);
+ ps->set_property (sym, value);
return SCM_UNSPECIFIED;
}
SCM sym = scm_car (s);
SCM val = scm_cadr (s);
- pr->internal_set_property (sym, val);
+ pr->set_property (sym, val);
}
return pr->unprotect ();
}
void
-Prob::internal_set_property (SCM sym, SCM val)
+#ifndef NDEBUG
+Prob::internal_set_property (SCM sym, SCM val, char const *file, int line, char const *fun)
+#else
+Prob::internal_set_property (SCM sym, SCM val)
+#endif
{
if (do_internal_type_checking_global)
type_check_assignment (sym, val);
{
SCM entry = scm_assoc (sym, alist);
if (scm_is_pair (entry))
- g->internal_set_property (sym, scm_cdr (entry));
+ g->set_property (sym, scm_cdr (entry));
}
}
SCM preset = p->get_property_data (sym);
if (val == SCM_EOL
|| scm_call_1 (type, preset) == SCM_BOOL_F)
- p->internal_set_property (sym, val);
+ p->set_property (sym, val);
}
if (!priority_found)
SCM vissym = ly_symbol2scm ("break-visibility");
SCM vis = bars_[0]->internal_get_property (vissym);
if (ly_is_equal (spanbar_->internal_get_property (vissym), vis))
- spanbar_->internal_set_property (vissym, vis);
+ spanbar_->set_property (vissym, vis);
spanbar_ = 0;
}
Bracket_nesting_group::create_grobs (Engraver *engraver, SCM default_type)
{
SCM type = scm_is_symbol (symbol_) ? symbol_ : default_type;
- delimiter_ = make_spanner_from_properties (engraver, type,
- SCM_EOL, ly_symbol2string (type).c_str ());
+ delimiter_ = engraver->make_spanner (ly_symbol2string (type).c_str (), SCM_EOL);
for (vsize i = 0 ; i < children_.size (); i++)
{
= robust_scm2drul (me->internal_get_property (sym), zero);
pair[xdir] = 0.0;
- me->internal_set_property (sym, ly_interval2scm (pair));
+ me->set_property (sym, ly_interval2scm (pair));
}
for (SCM s = ev->get_property ("tweaks");
scm_is_pair (s); s = scm_cdr (s))
{
- info.grob ()->internal_set_property (scm_caar (s), scm_cdar (s));
+ info.grob ()->set_property (scm_caar (s), scm_cdar (s));
}
}
}
&& current_reps == SCM_EOL || scm_is_pair (current_reps))
{
current_reps = scm_cons (what, current_reps);
- where->internal_set_property (reps, current_reps);
+ where->set_property (reps, current_reps);
}
}