X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Funpure-pure-container.cc;h=7a7d6d48d16d3c139aca38ad9f0f38f307b5debb;hb=0398fdb9df24ac2e22a8cbff1b3c18ca04e9f221;hp=3a2ab1e52de6ec64063b2c022a681cd3be900d03;hpb=1a3796c7166c453fc1ef5d30858e6bbb88fdb59f;p=lilypond.git diff --git a/lily/unpure-pure-container.cc b/lily/unpure-pure-container.cc index 3a2ab1e52d..7a7d6d48d1 100644 --- a/lily/unpure-pure-container.cc +++ b/lily/unpure-pure-container.cc @@ -19,24 +19,27 @@ */ #include "unpure-pure-container.hh" -#include "grob.hh" - -// Reroutes a call to the contained function after dropping last two -// arguments. Used for applying an "unpure" function in a "pure" +// Reroutes a call to the contained function after dropping second and +// third argument. Used for applying an "unpure" function in a "pure" // context. class Unpure_pure_call : public Smob1 { public: + static const char * const type_p_name_; // = 0 + // Smob procedures unfortunately can only take at most 3 SCM + // arguments. Otherwise we could use a "3, 0, 1" call signature and + // not require an argument count check of our own. LY_DECLARE_SMOB_PROC (&Unpure_pure_call::call, 2, 0, 1) - SCM call (SCM arg1, SCM arg2, SCM rest) + SCM call (SCM arg1, SCM, SCM rest) { - return scm_apply_0 (scm1 (), - scm_call_2 (ly_lily_module_constant ("drop-right"), - scm_cons2 (arg1, arg2, rest), - scm_from_int (2))); + if (!scm_is_pair (rest)) + scm_wrong_num_args (scm1 ()); + return scm_apply_1 (scm1 (), arg1, scm_cdr (rest)); } }; +const char * const Unpure_pure_call::type_p_name_ = 0; + SCM Unpure_pure_container::pure_part () const { @@ -63,7 +66,7 @@ LY_DEFINE (ly_unpure_pure_container_unpure_part, "ly:unpure-pure-container-unpur "Return the unpure part of @var{pc}.") { LY_ASSERT_SMOB (Unpure_pure_container, pc, 1); - return Unpure_pure_container::unsmob (pc)->unpure_part (); + return unsmob (pc)->unpure_part (); } LY_DEFINE (ly_unpure_pure_container_pure_part, "ly:unpure-pure-container-pure-part", @@ -71,11 +74,11 @@ LY_DEFINE (ly_unpure_pure_container_pure_part, "ly:unpure-pure-container-pure-pa "Return the pure part of @var{pc}.") { LY_ASSERT_SMOB (Unpure_pure_container, pc, 1); - return Unpure_pure_container::unsmob (pc)->pure_part (); + return unsmob (pc)->pure_part (); } int -Unpure_pure_container::print_smob (SCM port, scm_print_state *) +Unpure_pure_container::print_smob (SCM port, scm_print_state *) const { scm_puts ("#", port); return 1; } + +LY_DEFINE (ly_pure_call, "ly:pure-call", + 4, 0, 1, (SCM data, SCM grob, SCM start, SCM end, SCM rest), + "Convert property @var{data} (unpure-pure container or procedure)" + " to value in a pure context defined by @var{grob}," + " @var{start}, @var{end}, and possibly @var{rest} arguments.") +{ + if (Unpure_pure_container *upc = unsmob (data)) + { + // Avoid gratuitous creation of an Unpure_pure_call + if (upc->is_unchanging ()) + data = upc->unpure_part (); + else + { + data = upc->pure_part (); + if (ly_is_procedure (data)) + return scm_apply_3 (data, grob, start, end, rest); + return data; + } + } + if (ly_is_procedure (data)) + return scm_apply_1 (data, grob, rest); + return data; +} + +LY_DEFINE (ly_unpure_call, "ly:unpure-call", + 2, 0, 1, (SCM data, SCM grob, SCM rest), + "Convert property @var{data} (unpure-pure container or procedure)" + " to value in an unpure context defined by @var{grob}" + " and possibly @var{rest} arguments.") +{ + if (Unpure_pure_container *upc = unsmob (data)) + data = upc->unpure_part (); + if (ly_is_procedure (data)) + return scm_apply_1 (data, grob, rest); + return data; +}