/*
This file is part of LilyPond, the GNU music typesetter.
- Copyright (C) 2011--2012 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 "grob.hh"
-static scm_t_bits unpure_pure_container_tag;
-
-bool
-is_unpure_pure_container (SCM s)
-{
- return (SCM_NIMP (s) && SCM_CELL_TYPE (s) == unpure_pure_container_tag);
-}
-
-SCM
-unpure_pure_container_unpure_part (SCM smob)
+// Reroutes a call to the contained function after dropping last two
+// arguments. Used for applying an "unpure" function in a "pure"
+// context.
+class Unpure_pure_call : public Smob1<Unpure_pure_call>
{
- LY_ASSERT_TYPE (is_unpure_pure_container, smob, 1);
- return (SCM) SCM_CELL_WORD_1 (smob);
-}
+public:
+ LY_DECLARE_SMOB_PROC (2, 0, 1, (SCM self, SCM arg1, SCM arg2, SCM rest))
+ {
+ return scm_apply_0 (Unpure_pure_call::unsmob (self)->scm1 (),
+ scm_call_2 (ly_lily_module_constant ("drop-right"),
+ scm_cons2 (arg1, arg2, rest),
+ scm_from_int (2)));
+ }
+};
SCM
-unpure_pure_container_pure_part (SCM smob)
+Unpure_pure_container::pure_part () const
{
- LY_ASSERT_TYPE (is_unpure_pure_container, smob, 1);
- return (SCM) SCM_CELL_WORD_2 (smob);
+ return SCM_UNBNDP (scm2 ())
+ ? Unpure_pure_call::make_smob (scm1 ())
+ : scm2 ();
}
-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 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),
"Make an unpure-pure container. @var{unpure} should be an unpure"
" expression, and @var{pure} should be a pure expression. If @var{pure}"
- " is ommitted, the value of @var{unpure} will be used twice.")
+ " is omitted, the value of @var{unpure} will be used twice,"
+ " except that a callback is given two extra arguments"
+ " that are ignored for the sake of pure calculations.")
{
- SCM z;
-
- if (pure == SCM_UNDEFINED)
- 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 Unpure_pure_container::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 Unpure_pure_container::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 *)
{
scm_puts ("#<unpure-pure-container ", port);
- scm_display (unpure_pure_container_unpure_part (s), port);
- scm_puts (" ", port);
- scm_display (unpure_pure_container_pure_part (s), port);
+ scm_display (unpure_part (), port);
+ if (!is_unchanging ())
+ {
+ scm_puts (" ", port);
+ scm_display (pure_part (), port);
+ }
scm_puts (" >", port);
return 1;
}
-
-SCM
-pure_mark (SCM pure)
-{
- scm_gc_mark (unpure_pure_container_unpure_part (pure));
- scm_gc_mark (unpure_pure_container_pure_part (pure));
- return pure;
-}
-
-void init_unpure_pure_container ()
-{
- 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);
-};
-
-ADD_SCM_INIT_FUNC (unpure_pure_container, init_unpure_pure_container);