X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Funpure-pure-container.cc;h=143b2fd47de4c118e4b1818e94a9bc8c4779e01a;hb=90e4d7057f3857da049dfda3d130017d4719bd6b;hp=1aefe920afea8b647496d65bcadcb2baf10d2514;hpb=c39d188d28fdc84cef8cbaea7b8d6e2fb718c30f;p=lilypond.git diff --git a/lily/unpure-pure-container.cc b/lily/unpure-pure-container.cc index 1aefe920af..143b2fd47d 100644 --- a/lily/unpure-pure-container.cc +++ b/lily/unpure-pure-container.cc @@ -1,7 +1,7 @@ /* This file is part of LilyPond, the GNU music typesetter. - Copyright (C) 2011--2014 Mike Solomon + Copyright (C) 2011--2015 Mike Solomon LilyPond is free software: you can redistribute it and/or modify @@ -19,57 +19,33 @@ */ #include "unpure-pure-container.hh" -#include "grob.hh" - -static scm_t_bits unpure_pure_container_tag; -static scm_t_bits unpure_pure_call_tag; -// Used for rerouting a function of (grob start end) to one of -// (grob) - -bool -is_unpure_pure_container (SCM s) +// 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 { - return (SCM_NIMP (s) && SCM_CELL_TYPE (s) == unpure_pure_container_tag); -} - -bool -is_unchanging_unpure_pure_container (SCM s) -// A container that has the same callback for both 'pure' and 'unpure' lookups -// and which ignores the 'start' and 'end' columnns. -// Such a callback will give the same answer for tentative or final layouts. -{ - LY_ASSERT_TYPE (is_unpure_pure_container, s, 1); - SCM pure_part = SCM_SMOB_OBJECT_2 (s); - return (SCM_UNBNDP (pure_part)); -} +public: + // 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, SCM rest) + { + if (!scm_is_pair (rest)) + scm_wrong_num_args (scm1 ()); + return scm_apply_1 (scm1 (), arg1, scm_cdr (rest)); + } +}; SCM -unpure_pure_container_unpure_part (SCM smob) +Unpure_pure_container::pure_part () const { - LY_ASSERT_TYPE (is_unpure_pure_container, smob, 1); - return SCM_SMOB_OBJECT (smob); + return SCM_UNBNDP (scm2 ()) + ? Unpure_pure_call::make_smob (scm1 ()) + : scm2 (); } -SCM -unpure_pure_container_pure_part (SCM smob) -{ - LY_ASSERT_TYPE (is_unpure_pure_container, smob, 1); - SCM res = SCM_SMOB_OBJECT_2 (smob); - - if (!SCM_UNBNDP (res)) - return res; - - SCM_NEWSMOB (res, unpure_pure_call_tag, - SCM_UNPACK (unpure_pure_container_unpure_part (smob))); - return res; -} - -LY_DEFINE (ly_unpure_pure_container_p, "ly:unpure-pure-container?", - 1, 0, 0, (SCM clos), - "Is @var{clos} an unpure pure container?") -{ - return scm_from_bool (is_unpure_pure_container (clos)); -} +const char * const Unpure_pure_container::type_p_name_ = "ly:unpure-pure-container?"; LY_DEFINE (ly_make_unpure_pure_container, "ly:make-unpure-pure-container", 1, 1, 0, (SCM unpure, SCM pure), @@ -79,76 +55,72 @@ LY_DEFINE (ly_make_unpure_pure_container, "ly:make-unpure-pure-container", " except that a callback is given two extra arguments" " that are ignored for the sake of pure calculations.") { - SCM z; - - if (SCM_UNBNDP (pure) && !ly_is_procedure (unpure)) - pure = unpure; - - SCM_NEWSMOB2 (z, unpure_pure_container_tag, SCM_UNPACK (unpure), SCM_UNPACK (pure)); - return z; + return Unpure_pure_container::make_smob (unpure, pure); } LY_DEFINE (ly_unpure_pure_container_unpure_part, "ly:unpure-pure-container-unpure-part", 1, 0, 0, (SCM pc), "Return the unpure part of @var{pc}.") { - LY_ASSERT_TYPE (is_unpure_pure_container, pc, 1); - return unpure_pure_container_unpure_part (pc); + LY_ASSERT_SMOB (Unpure_pure_container, pc, 1); + return unsmob (pc)->unpure_part (); } LY_DEFINE (ly_unpure_pure_container_pure_part, "ly:unpure-pure-container-pure-part", 1, 0, 0, (SCM pc), "Return the pure part of @var{pc}.") { - LY_ASSERT_TYPE (is_unpure_pure_container, pc, 1); - return unpure_pure_container_pure_part (pc); + LY_ASSERT_SMOB (Unpure_pure_container, pc, 1); + return unsmob (pc)->pure_part (); } int -print_unpure_pure_container (SCM s, SCM port, scm_print_state *) +Unpure_pure_container::print_smob (SCM port, scm_print_state *) const { scm_puts ("#", port); return 1; } -SCM -pure_mark (SCM smob) +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.") { - scm_gc_mark (SCM_SMOB_OBJECT (smob)); - return SCM_SMOB_OBJECT_2 (smob); -} - -// Function signature has two fixed arguments so that dropping two -// will always work: if we have fewer to start with, it will trigger -// wrong-number-of-args in a sensible location rather than making -// drop-right barf. - -SCM -apply_unpure_pure (SCM clo, SCM arg1, SCM arg2, SCM rest) -{ - return scm_apply_0 (SCM_SMOB_OBJECT (clo), - scm_call_2 (ly_lily_module_constant ("drop-right"), - scm_cons2 (arg1, arg2, rest), - scm_from_int (2))); + 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; } - -void init_unpure_pure_container () +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.") { - unpure_pure_container_tag = scm_make_smob_type ("unpure-pure-container", 0); - scm_set_smob_mark (unpure_pure_container_tag, pure_mark); - scm_set_smob_print (unpure_pure_container_tag, print_unpure_pure_container); - unpure_pure_call_tag = scm_make_smob_type ("unpure-pure-call", 0); - scm_set_smob_mark (unpure_pure_call_tag, scm_markcdr); - scm_set_smob_apply (unpure_pure_call_tag, - (scm_t_subr) apply_unpure_pure, 2, 0, 1); -}; - -ADD_SCM_INIT_FUNC (unpure_pure_container, init_unpure_pure_container); + 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; +}