]> git.donarmstrong.com Git - lilypond.git/blob - lily/include/smobs.hh
Run grand-replace (issue 3765)
[lilypond.git] / lily / include / smobs.hh
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1999--2014 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 SMOBS_HH
21 #define SMOBS_HH
22
23 #include "lily-guile.hh"
24 #include "warn.hh"
25
26 /*
27   Smobs are GUILEs mechanism of exporting C(++) objects to the Scheme
28   world.  They are documented in the GUILE manual.
29
30
31   In LilyPond, smobs are created from C++ objects through macros.
32   There are two types of smob objects.
33
34   1. Simple smobs are intended for simple objects like numbers:
35   immutable objects that can be copied without change of meaning.
36
37   To obtain an SCM version of a simple smob, use the member function
38   SCM smobbed_copy ().
39
40   Simple smobs are created by adding the
41   DECLARE_SIMPLE_SMOBS(Classname) to the declaration
42
43   A simple smob is only optionally under the reign of the GUILE
44   garbage collector: its usual life time is that of a normal C++
45   object.  While a smobbed_copy () is fully under control of the
46   garbage collector and will have its mark_smob function called during
47   garbage collection, an automatic variable of this type will not have
48   mark_smob called, but rather have its memory image in the call stack
49   scanned for contained non-immediate SCM values.  Anything requiring
50   more complex mark_smob behavior is not suitable for a simple smob.
51
52   When you create a smobbed_copy, the _copy_ is fully managed by the
53   GUILE memory system.  As a corollary, multiple smobbed_copy calls
54   yield multiple GUILE objects generally not eq? to each other.
55
56   2. Complex smobs are objects that have an identity. These objects
57   carry this identity in the form of a self_scm () method, which is a
58   SCM pointer to the object itself.  Complex smobs are always under
59   control of the GUILE memory system.
60
61   The constructor for a complex smob should have 3 steps:
62
63   * initialize all SCM members to an immediate value (like SCM_EOL)
64
65   * call smobify_self ()
66
67   * initialize SCM members
68
69   For example,
70
71   Complex_smob::Complex_smob () {
72   scm_member_ = SCM_EOL;
73   smobify_self ();
74   scm_member_ = <..what you want to store..>
75   }
76
77   after construction, the self_scm () field of a complex smob is
78   protected from Garbage Collection.  This protection should be
79   removed once the object is put into another (reachable) Scheme data
80   structure, i.e.
81
82   Complex_smob *p = new Complex_smob;
83   list = scm_cons (p->self_scm (), list);
84   p->unprotect ();
85
86   Since unprotect returns the SCM object itself, this particular case
87   can be written as
88
89   Complex_smob *p = new Complex_smob;
90   list = scm_cons (p->unprotect (), list);
91
92   Complex smobs are made with DECLARE_SMOBS (Classname) in the class
93   declaration.
94
95   CALLING INTERFACE
96
97   Common public methods to C++ smob objects:
98
99   unsmob (SCM x)  - unpacks X and returns pointer to the C++ object, or 0
100   if it has the wrong type.
101
102   SCM equal_p (SCM a, SCM b) - compare A and B. Returns a Scheme boolean
103
104
105   IMPLEMENTATION
106
107   For implementating a class, the following should be provided
108
109   - an equal_p () function (a default is in the
110   IMPLEMENT_DEFAULT_EQUAL_P macro in ly-smobs.icc)
111
112   - mark_smob () function, that calls scm_gc_mark () on all Scheme
113   objects in the class
114
115   - a print_smob () function, that displays a representation for
116   debugging purposes
117
118   - A call to one of the IMPLEMENT_SMOBS or IMPLEMENT_SIMPLE_SMOBS macros
119   from file "ly-smobs.icc"
120 */
121
122 #define DECLARE_SIMPLE_SMOBS(CL)                \
123   public:                                       \
124   SCM smobbed_copy () const;                    \
125   DECLARE_BASE_SMOBS (CL)
126
127 #define DECLARE_BASE_SMOBS(CL)                                  \
128   friend class Non_existent_class;                              \
129   private:                                                      \
130   static const char* smob_name_; \
131   static scm_t_bits smob_tag_;                                  \
132   static SCM mark_smob (SCM);                                   \
133   static size_t free_smob (SCM s);                              \
134   static int print_smob (SCM s, SCM p, scm_print_state*);       \
135   public:                                                       \
136   static SCM equal_p (SCM a, SCM b);                            \
137   static CL *unsmob (SCM s) __attribute__((pure))               \
138   {                                                             \
139     if (SCM_NIMP (s) && SCM_CELL_TYPE (s) == smob_tag_)         \
140       return (CL *) SCM_CELL_WORD_1 (s);                        \
141     else                                                        \
142       return 0;                                                 \
143   }                                                             \
144   static SCM smob_p (SCM);                                      \
145   static void init_smobs ();                                    \
146   private:
147
148 #define DECLARE_SMOBS(CL)                       \
149   DECLARE_BASE_SMOBS (CL)                       \
150     protected:                                  \
151   virtual ~CL ();                               \
152   SCM unprotected_smobify_self ();              \
153   private:                                      \
154   void smobify_self ();                         \
155   SCM self_scm_;                                \
156   SCM protection_cons_;                         \
157   public:                                       \
158   SCM unprotect ();                             \
159   void protect ();                              \
160   SCM self_scm () const { return self_scm_; }   \
161   private:
162
163 #define DECLARE_UNSMOB(CL, name)                \
164   inline CL *                                   \
165   unsmob_ ## name (SCM s)                       \
166   {                                             \
167     return CL::unsmob (s);                      \
168   }
169
170 #define DECLARE_TYPE_P(CL) extern SCM CL ## _type_p_proc
171
172 void protect_smob (SCM smob, SCM *prot_cons);
173 void unprotect_smob (SCM smob, SCM *prot_cons);
174
175 extern bool parsed_objects_should_be_dead;
176 class parsed_dead
177 {
178   static vector<parsed_dead *> elements;
179   SCM data;
180   SCM readout_one ()
181   {
182     SCM res = data;
183     data = SCM_UNDEFINED;
184     return res;
185   }
186 public:
187   parsed_dead () : data (SCM_UNDEFINED)
188   {
189     elements.push_back (this);
190   }
191   void checkin (SCM arg) { data = arg; }
192   static SCM readout ();
193 };
194
195 #ifndef NDEBUG
196 #define ASSERT_LIVE_IS_ALLOWED(arg)                                     \
197   do {                                                                  \
198     static parsed_dead pass_here;                                       \
199     if (parsed_objects_should_be_dead)                                  \
200       pass_here.checkin (arg);                                          \
201   } while (0)
202 #else
203 #define ASSERT_LIVE_IS_ALLOWED(arg) do { (void)(arg); }  \
204   while (0)
205 #endif
206
207 #endif /* SMOBS_HH */
208