]> git.donarmstrong.com Git - lilypond.git/blob - lily/unpure-pure-container.cc
Run grand-replace (issue 3765)
[lilypond.git] / lily / unpure-pure-container.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 2011--2014 Mike Solomon <mike@mikesolomon.org>
5
6
7   LilyPond is free software: you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation, either version 3 of the License, or
10   (at your option) any later version.
11
12   LilyPond is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
19 */
20 #include "unpure-pure-container.hh"
21
22 #include "grob.hh"
23
24 static scm_t_bits unpure_pure_container_tag;
25 static scm_t_bits unpure_pure_call_tag;
26 // Used for rerouting a function of (grob start end) to one of
27 // (grob)
28
29 bool
30 is_unpure_pure_container (SCM s)
31 {
32   return (SCM_NIMP (s) && SCM_CELL_TYPE (s) == unpure_pure_container_tag);
33 }
34
35 bool
36 is_unchanging_unpure_pure_container (SCM s)
37 // A container that has the same callback for both 'pure' and 'unpure' lookups
38 // and which ignores the 'start' and 'end' columnns.
39 // Such a callback will give the same answer for tentative or final layouts.
40 {
41   LY_ASSERT_TYPE (is_unpure_pure_container, s, 1);
42   SCM pure_part = SCM_SMOB_OBJECT_2 (s);
43   return (SCM_UNBNDP (pure_part));
44 }
45
46 SCM
47 unpure_pure_container_unpure_part (SCM smob)
48 {
49   LY_ASSERT_TYPE (is_unpure_pure_container, smob, 1);
50   return SCM_SMOB_OBJECT (smob);
51 }
52
53 SCM
54 unpure_pure_container_pure_part (SCM smob)
55 {
56   LY_ASSERT_TYPE (is_unpure_pure_container, smob, 1);
57   SCM res = SCM_SMOB_OBJECT_2 (smob);
58
59   if (!SCM_UNBNDP (res))
60     return res;
61
62   SCM_NEWSMOB (res, unpure_pure_call_tag,
63                SCM_UNPACK (unpure_pure_container_unpure_part (smob)));
64   return res;
65 }
66
67 LY_DEFINE (ly_unpure_pure_container_p, "ly:unpure-pure-container?",
68            1, 0, 0, (SCM clos),
69            "Is @var{clos} an unpure pure container?")
70 {
71   return scm_from_bool (is_unpure_pure_container (clos));
72 }
73
74 LY_DEFINE (ly_make_unpure_pure_container, "ly:make-unpure-pure-container",
75            1, 1, 0, (SCM unpure, SCM pure),
76            "Make an unpure-pure container.  @var{unpure} should be an unpure"
77            " expression, and @var{pure} should be a pure expression.  If @var{pure}"
78            " is omitted, the value of @var{unpure} will be used twice,"
79            " except that a callback is given two extra arguments"
80            " that are ignored for the sake of pure calculations.")
81 {
82   SCM z;
83
84   if (SCM_UNBNDP (pure) && !ly_is_procedure (unpure))
85     pure = unpure;
86
87   SCM_NEWSMOB2 (z, unpure_pure_container_tag, SCM_UNPACK (unpure), SCM_UNPACK (pure));
88   return z;
89 }
90
91 LY_DEFINE (ly_unpure_pure_container_unpure_part, "ly:unpure-pure-container-unpure-part",
92            1, 0, 0, (SCM pc),
93            "Return the unpure part of @var{pc}.")
94 {
95   LY_ASSERT_TYPE (is_unpure_pure_container, pc, 1);
96   return unpure_pure_container_unpure_part (pc);
97 }
98
99 LY_DEFINE (ly_unpure_pure_container_pure_part, "ly:unpure-pure-container-pure-part",
100            1, 0, 0, (SCM pc),
101            "Return the pure part of @var{pc}.")
102 {
103   LY_ASSERT_TYPE (is_unpure_pure_container, pc, 1);
104   return unpure_pure_container_pure_part (pc);
105 }
106
107 int
108 print_unpure_pure_container (SCM s, SCM port, scm_print_state *)
109 {
110   scm_puts ("#<unpure-pure-container ", port);
111   scm_display (unpure_pure_container_unpure_part (s), port);
112   if (!SCM_UNBNDP (SCM_SMOB_OBJECT_2 (s)))
113     {
114       scm_puts (" ", port);
115       scm_display (unpure_pure_container_pure_part (s), port);
116     }
117   scm_puts (" >", port);
118   return 1;
119 }
120
121 SCM
122 pure_mark (SCM smob)
123 {
124   scm_gc_mark (SCM_SMOB_OBJECT (smob));
125   return SCM_SMOB_OBJECT_2 (smob);
126 }
127
128 // Function signature has two fixed arguments so that dropping two
129 // will always work: if we have fewer to start with, it will trigger
130 // wrong-number-of-args in a sensible location rather than making
131 // drop-right barf.
132
133 SCM
134 apply_unpure_pure (SCM clo, SCM arg1, SCM arg2, SCM rest)
135 {  
136   return scm_apply_0 (SCM_SMOB_OBJECT (clo),
137                       scm_call_2 (ly_lily_module_constant ("drop-right"),
138                                   scm_cons2 (arg1, arg2, rest),
139                                   scm_from_int (2)));
140 }
141   
142
143 void init_unpure_pure_container ()
144 {
145   unpure_pure_container_tag = scm_make_smob_type ("unpure-pure-container", 0);
146   scm_set_smob_mark (unpure_pure_container_tag, pure_mark);
147   scm_set_smob_print (unpure_pure_container_tag, print_unpure_pure_container);
148   unpure_pure_call_tag = scm_make_smob_type ("unpure-pure-call", 0);
149   scm_set_smob_mark (unpure_pure_call_tag, scm_markcdr);
150   scm_set_smob_apply (unpure_pure_call_tag,
151                       (scm_t_subr) apply_unpure_pure, 2, 0, 1);
152 };
153
154 ADD_SCM_INIT_FUNC (unpure_pure_container, init_unpure_pure_container);