]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/unpure-pure-container.cc
Web-ja: update introduction
[lilypond.git] / lily / unpure-pure-container.cc
index 1aefe920afea8b647496d65bcadcb2baf10d2514..143b2fd47de4c118e4b1818e94a9bc8c4779e01a 100644 (file)
@@ -1,7 +1,7 @@
 /*
   This file is part of LilyPond, the GNU music typesetter.
 
-  Copyright (C) 2011--2014 Mike Solomon <mike@mikesolomon.org>
+  Copyright (C) 2011--2015 Mike Solomon <mike@mikesolomon.org>
 
 
   LilyPond is free software: you can redistribute it and/or modify
 */
 #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<Unpure_pure_call>
 {
-  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<Unpure_pure_container> (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<Unpure_pure_container> (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 ("#<unpure-pure-container ", port);
-  scm_display (unpure_pure_container_unpure_part (s), port);
-  if (!SCM_UNBNDP (SCM_SMOB_OBJECT_2 (s)))
+  scm_display (unpure_part (), port);
+  if (!is_unchanging ())
     {
       scm_puts (" ", port);
-      scm_display (unpure_pure_container_pure_part (s), port);
+      scm_display (pure_part (), port);
     }
   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<Unpure_pure_container> (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<Unpure_pure_container> (data))
+    data = upc->unpure_part ();
+  if (ly_is_procedure (data))
+    return scm_apply_1 (data, grob, rest);
+  return data;
+}