1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3 
4   Copyright (C) 1997--2021 Han-Wen Nienhuys <hanwen@xs4all.nl>
5 
6   LilyPond is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10 
11   LilyPond is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15 
16   You should have received a copy of the GNU General Public License
17   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #ifndef MUSIC_ITERATOR_HH
21 #define MUSIC_ITERATOR_HH
22 
23 #include "diagnostics.hh"
24 #include "moment.hh"
25 #include "virtual-methods.hh"
26 #include "context-handle.hh"
27 
28 #include <functional>
29 
30 /**
31    ---
32 
33    Music_iterator is an object type that traverses the Music structure and
34    reports the events it finds to interpretation contexts. It is not yet
35    user-serviceable.
36 
37 
38    ---
39 
40    Conceptually, a music-iterator traverses a queue of pending musical events.
41    This way of viewing and traversing music-expressions does not require an
42    actual queue.
43 
44 
45    ok () -- processing is incomplete: the queue still holds events or the
46    iterator wants to continue regardless
47 
48    pending_moment () -- the time of the next event in the queue (+infinity
49    once the queue is empty)
50 
51    process (M) -- process all at M (Precondition: no events exist
52    before M, ok () holds).  Side-effects:
53 
54    * This removes all events at M from the pending queue.
55 
56    * Typically this reports the music to an interpretation context,
57    thus changing the state of the interpretation context.
58 
59    run_always () -- when true, process (M) should be called even if M is
60    earlier than pending_moment (); when false, process (M) should not be
61    called until M reaches pending_moment ()
62 
63    TODO:
64 
65    merge pending_moment and process?
66 */
67 class Music_iterator : public Smob<Music_iterator>, public Diagnostics
68 {
69 public:
70   int print_smob (SCM, scm_print_state *) const;
71   SCM mark_smob () const;
72   static const char *const type_p_name_;
73   virtual ~Music_iterator ();
74   Input *origin () const override;
75 
76   VIRTUAL_CLASS_NAME (Music_iterator);
77 private:
78   Music_iterator (Music_iterator const &) = delete;
79   Music_iterator &operator = (Music_iterator const &) = delete;
80 
81 public:
music_get_length() const82   const Moment &music_get_length () const { return music_length_; }
83   // music_start_mom () is calculated relative to the time where the
84   // iterator occurs in the music stream, so it will usually be
85   // non-zero only for expressions starting with grace notes.
music_start_mom() const86   const Moment &music_start_mom () const { return start_mom_; }
87   void report_event (Music *);
88 
89   // N.B. Subclasses can modify the behavior of these to address a child
90   // iterator.  Where it is important to avoid that, use get_own_context () and
91   // set_own_context () instead.
get_context() const92   virtual Context *get_context () const { return get_own_context (); }
set_context(Context * c)93   virtual void set_context (Context *c) { set_own_context (c); }
94 
95   // Circumvent the virtual get_context () and set_context () to address the
96   // context of this very iterator.
get_own_context() const97   Context *get_own_context () const { return handle_.get_context (); }
set_own_context(Context * c)98   void set_own_context (Context *c) { handle_.set_context (c); }
99 
100   // Replace this iterator's references to one context with another.  This is
101   // not recursive.  Subclasses that track multiple contexts should override
102   // this to consider them all.
103   virtual void substitute_context (Context *from, Context *to);
104 
105   // Create an iterator that has no parent.
create_top_iterator(Music * mus)106   static SCM create_top_iterator (Music *mus)
107   {
108     return create_iterator (nullptr, mus);
109   }
110 
111   // Create an iterator that has this iterator as its parent.
create_child(Music * mus)112   SCM create_child (Music *mus)
113   {
114     return create_iterator (this, mus);
115   }
116 
117   void init_context (Context *);
118   void quit ();
119 
120   virtual Moment pending_moment () const;
ok() const121   bool ok () const
122   {
123     return (pending_moment () < Moment::infinity ())
124            || run_always ();
125   }
126   virtual bool run_always () const;
127   // process is called with a time relative to the iterator start, so
128   // usually the last processed moment is the same as music_get_length.
129   virtual void process (Moment until);
130   virtual void derived_mark () const;
131   DECLARE_SCHEME_CALLBACK (constructor, ());
132 
133   Music *get_music () const;
134 
135   // Call the given function on this iterator and then on all of its children.
136   //
137   // Subclasses with child iterators must override this method, call the
138   // inherited implementation first, and then call preorder_walk for each
139   // child.
140   virtual void
preorder_walk(const std::function<void (Music_iterator *)> & visit)141   preorder_walk (const std::function <void (Music_iterator *)> &visit)
142   {
143     if (visit)
144       visit (this);
145   }
146 
get_parent() const147   Music_iterator *get_parent () const { return parent_; }
148 
149   // Scoped search for music by type: look in this iterator's music, then
150   // search the ancestors up to the top.  Return the first iterator whose music
151   // has the given type (null if none does).
152   Music_iterator *find_above_by_music_type (SCM type_sym) const;
153 
154   // Scoped property access: look in this iterator's music, then search the
155   // ancestors up to the top.
internal_get_property(SCM name_sym) const156   SCM internal_get_property (SCM name_sym) const
157   {
158     SCM value = SCM_EOL;
159     internal_where_defined (name_sym, &value);
160     return value;
161   }
162 
163   // Scoped property access: look in this iterator's music, then search the
164   // ancestors up to the top.  Return the iterator whose music has the named
165   // property (null if none does).  Optionally get the value of the property.
166   Music_iterator *internal_where_defined (SCM name_sym, SCM *value) const;
internal_where_defined(SCM name_sym) const167   Music_iterator *internal_where_defined (SCM name_sym) const
168   {
169     SCM value;
170     return internal_where_defined (name_sym, &value);
171   }
172 
173   // Scoped search for taggged music: look in this iterator's music, then
174   // search the ancestors up to the top.  Return the first iterator whose music
175   // is tagged with the given tag.  If none is found, return this iterator.
176   Music_iterator *where_tagged (SCM tag_sym) const;
177 
178 protected:
179   Music_iterator ();
180 
181   // During the staged initialization of this iterator, this method is called
182   // after the iterator has received its music, but before it receives its
183   // context.  This is the first chance to initialize state that depends on
184   // music properties, and the last chance to initialize state required for
185   // timing.  When this method is overridden, it is usually because the
186   // iterator manages child iterators, which must be created to contribute to
187   // timing calculations.
create_children()188   virtual void create_children () {}
189 
190   // During the staged initialization of this iterator, this method is called
191   // after the iterator's own context has been initialized.  It must initialize
192   // the contexts of any child iterators.
193   //
194   // Think twice before reading context properties here.  Other iterators'
195   // process () methods may run after this call and before this iterator's
196   // process () method runs (and may change the context properties).
create_contexts()197   virtual void create_contexts () {}
198 
199   void descend_to_bottom_context ();
200   void descend_to_child (Context *);
201   void descend_to_user_accessible_context ();
202 
203   virtual void do_quit ();
204 
205 private:
206   static SCM create_iterator (Music_iterator *parent, Music *mus);
207 
208 private:
209   Music_iterator *parent_ = nullptr;
210   Context_handle handle_;
211   Music *music_ = nullptr;
212   Moment music_length_;
213   Moment start_mom_;
214 };
215 
216 bool is_child_context (Context *me, Context *child);
217 
218 #define IMPLEMENT_CTOR_CALLBACK(Class)                                  \
219   LY_DEFINE_MEMBER_FUNCTION (Class, constructor, \
220                              mangle_cxx_identifier (#Class "::constructor").c_str(), \
221                              0, 0, 0,                                   \
222                              (),                                        \
223                              "")                                        \
224   {                                                                     \
225     Class *c = (new Class);                                             \
226     return c->unprotect ();                                             \
227   }
228 
229 #endif // MUSIC_ITERATOR_HH
230