]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/translator-def.cc
2003 -> 2004
[lilypond.git] / lily / translator-def.cc
index 7f0a2bb34a336a3d3a03be2d7dfb2422a3f5f656..f2037b227666833bde4c56c43a3e2e713ec6dd8f 100644 (file)
 /*   
-  translator-def.cc --  implement Translator_def
+  translator-def.cc --  implement Context_def
   
   source file of the GNU LilyPond music typesetter
   
-  (c) 2000--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+  (c) 2000--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
   
  */
 
 #include "lily-proto.hh"
-#include "translator-def.hh"
+#include "context-def.hh"
 #include "translator-group.hh"
 #include "warn.hh"
 #include "music-output-def.hh"
-
 #include "ly-smobs.icc"
 
 int
-Translator_def::print_smob (SCM smob, SCM port, scm_print_state*)
+Context_def::print_smob (SCM smob, SCM port, scm_print_state*)
 {
-  Translator_def* me = (Translator_def*) SCM_CELL_WORD_1 (smob);
+  Context_def* me = (Context_def*) SCM_CELL_WORD_1 (smob);
 
-  scm_puts ("#<Translator_def ", port);
-  scm_display (me->type_name_, port);
+  scm_puts ("#<Context_def ", port);
+  scm_display (me->context_name_, port);
   scm_puts (">", port);
   return 1;
 }
 
 
 SCM
-Translator_def::mark_smob (SCM smob)
+Context_def::mark_smob (SCM smob)
 {
-  Translator_def* me = (Translator_def*) SCM_CELL_WORD_1 (smob);
+  Context_def* me = (Context_def*) SCM_CELL_WORD_1 (smob);
 
-  scm_gc_mark (me->type_aliases_);
-  scm_gc_mark (me->consists_name_list_);
-  scm_gc_mark (me->accepts_name_list_);
-  scm_gc_mark (me->end_consists_name_list_);
+  scm_gc_mark (me->description_);
+  scm_gc_mark (me->context_aliases_);
+  scm_gc_mark (me->accept_mods_);
+  scm_gc_mark (me->translator_mods_);
   scm_gc_mark (me->property_ops_);  
   scm_gc_mark (me->translator_group_type_);
-  return me->type_name_;
+  return me->context_name_;
 }
 
-SCM push_sym;
-SCM assign_sym;
 
-static void
-foo_init ()
+Context_def::Context_def ()
 {
-  push_sym = scm_permanent_object (ly_symbol2scm ("push"));
-  assign_sym = scm_permanent_object (ly_symbol2scm ("assign"));
-}
-
-ADD_SCM_INIT_FUNC (transdef, foo_init);
-
-Translator_def::Translator_def ()
-{
-  type_aliases_ = SCM_EOL;
+  context_aliases_ = SCM_EOL;
   translator_group_type_ = SCM_EOL;
-  accepts_name_list_ = SCM_EOL;   
-  consists_name_list_ = SCM_EOL;
-  end_consists_name_list_ = SCM_EOL;
+  accept_mods_ = SCM_EOL;
+  translator_mods_ = SCM_EOL;
   property_ops_ = SCM_EOL;
-  type_name_ = SCM_EOL;
+  context_name_ = SCM_EOL;
+  description_ = SCM_EOL;
+
+  smobify_self();
 }
-Translator_def::~Translator_def ()
+
+Context_def::~Context_def ()
 {
 }
 
-Translator_def::Translator_def (Translator_def const & s)
+Context_def::Context_def (Context_def const & s)
   : Input (s)
 {
-  consists_name_list_ = scm_list_copy (s.consists_name_list_);
-  end_consists_name_list_ = scm_list_copy (s.end_consists_name_list_);
-  accepts_name_list_ = scm_list_copy (s.accepts_name_list_);
-  property_ops_ = scm_list_copy (s.property_ops_);
-  type_aliases_ = s.type_aliases_;
+  context_aliases_ = SCM_EOL;
+  translator_group_type_ = SCM_EOL;
+  accept_mods_ = SCM_EOL;   
+  translator_mods_ = SCM_EOL;
+  property_ops_ = SCM_EOL;
+  context_name_ = SCM_EOL;
+  description_ = SCM_EOL;
+  
+  smobify_self();
+  description_ = s.description_;
+
+  accept_mods_ = s.accept_mods_;
+  property_ops_ = s.property_ops_;
+  translator_mods_ = s.translator_mods_;
+  context_aliases_ = s.context_aliases_;
   translator_group_type_ = s.translator_group_type_;
-  type_name_ = s.type_name_;
+  context_name_ = s.context_name_;
 }
 
 
-
 void
-Translator_def::set_acceptor (SCM name, bool add)
+Context_def::add_context_mod (SCM mod)
 {
-  if (add)
-    this->accepts_name_list_ = gh_cons (name, this->accepts_name_list_);
-  else
-    this->accepts_name_list_ = scm_delete_x (name, this->accepts_name_list_);
-}
-
-
-SCM
-Translator_def::modify_definition (SCM list, SCM str, bool add)
-{
-  String s = ly_scm2string (str);
-  if (!get_translator_l (s))
-    error (_ ("Program has no such type"));
+  SCM tag  = gh_car (mod);
+  if (ly_symbol2scm ("description")  == tag)
+    {
+      description_ = gh_cadr (mod);
+      return ;
+    }
 
-  if (add)
+  SCM sym = gh_cadr (mod);
+  if (gh_string_p (sym))
+    sym = scm_string_to_symbol (sym);
+  
+  if (ly_symbol2scm ("consists") == tag
+      || ly_symbol2scm ("consists-end") == tag
+      || ly_symbol2scm ("remove") == tag)
     {
-      if (scm_memq (str, list) != SCM_BOOL_F)
-       {
-         warning (_f ("Already contains: `%s'", s));
-         warning (_f ("Not adding translator: `%s'", s));
-       }
+      if (!get_translator (sym))
+       error (_f ("Program has no such type: `%s'", ly_symbol2string (sym).to_str0 ()));
       else
-       list= gh_cons (str, list);
+       translator_mods_ = gh_cons (scm_list_2 (tag, sym), translator_mods_ );
+    }
+  else if (ly_symbol2scm ("accepts") == tag
+          || ly_symbol2scm ("denies") == tag)
+    {
+      accept_mods_ = gh_cons (scm_list_2 (tag, sym), accept_mods_); 
+    }
+  else if (ly_symbol2scm ("poppush") == tag
+          || ly_symbol2scm ("pop") == tag
+          || ly_symbol2scm ("push") == tag
+          || ly_symbol2scm ("assign") == tag
+          || ly_symbol2scm ("unset") == tag)
+    {
+      property_ops_ = gh_cons (mod, property_ops_);
+    }
+  else if (ly_symbol2scm ("alias") == tag)
+    {
+      context_aliases_ = gh_cons (sym, context_aliases_);
+    }
+  else if (ly_symbol2scm ("translator-type")  == tag)
+    {
+      translator_group_type_ = sym;
+    }
+  else if (ly_symbol2scm ("context-name")  == tag)
+    {
+      context_name_ = sym;
     }
   else
     {
-      list = scm_delete_x (str, list);
+      programming_error ("Unknown context mod tag.");
     }
-  return list;
 }
 
 
 
-void
-Translator_def::remove_element (SCM s)
-{
-  this->end_consists_name_list_ = modify_definition (this->end_consists_name_list_, s, false);
-  this->consists_name_list_ = modify_definition (this->consists_name_list_, s, false);
-}
-
-void
-Translator_def::add_element (SCM s)
-{
-  this->consists_name_list_ = modify_definition (this->consists_name_list_, s, true);
-}
-
-void
-Translator_def::add_last_element (SCM s)
-{
-  this->end_consists_name_list_ = modify_definition (this->end_consists_name_list_, s, true);
-}
-void
-Translator_def::add_push_property (SCM props, SCM syms,  SCM vals)
-{
-  this->property_ops_ = gh_cons (scm_list_n (push_sym, props, syms, vals, SCM_UNDEFINED),
-                                this->property_ops_);
-}
-
-void
-Translator_def::add_pop_property (SCM props, SCM syms)
+SCM
+Context_def::get_context_name () const
 {
-  this->property_ops_ = gh_cons (scm_list_n (push_sym, props, syms, SCM_UNDEFINED),
-                                this->property_ops_);
+  return context_name_;
 }
 
-/*
-  Do it. SYMS maybe a symbol or a list of symbols. VAL is
-  SCM_UNDEFINED in case of a pop
-*/
-void
-Translator_def::apply_pushpop_property (Translator_group* me,SCM syms, SCM eprop, SCM val)
+SCM
+Context_def::get_accepted (SCM user_mod) const
 {
-  if (gh_symbol_p (syms))
-    dynamic_cast<Translator_group*> (me)->execute_single_pushpop_property (syms, eprop, val);
-  else for (SCM s = syms; gh_pair_p (s); s = ly_cdr (s))
-    dynamic_cast<Translator_group*> (me)->execute_single_pushpop_property (ly_car (s), eprop, val);
+  SCM mods = scm_reverse_x (scm_list_copy (accept_mods_),
+                           user_mod);
+  SCM acc = SCM_EOL;
+  for (SCM s = mods; gh_pair_p (s); s = gh_cdr (s))
+    {
+      SCM tag = gh_caar (s);
+      SCM sym = gh_cadar (s);
+      if (tag == ly_symbol2scm ("accepts"))
+       acc = gh_cons (sym, acc);
+      else if (tag == ly_symbol2scm ("denies"))
+       acc = scm_delete_x (sym, acc);
+    }
+  return acc;
 }
 
-
-
-Link_array<Translator_def>
-Translator_def::path_to_acceptable_translator (SCM type_str, Music_output_def* odef) const
+          
+Link_array<Context_def>
+Context_def::path_to_acceptable_translator (SCM type_sym, Music_output_def* odef) const
 {
-  assert (gh_string_p (type_str));
+  assert (gh_symbol_p (type_sym));
   
-  Link_array<Translator_def> accepted_arr;
-  for (SCM s = accepts_name_list_; gh_pair_p (s); s = ly_cdr (s))
+  SCM accepted = get_accepted (SCM_EOL);
+
+  Link_array<Context_def> accepteds;
+  for (SCM s = accepted; gh_pair_p (s); s = ly_cdr (s))
     {
-      Translator_def *t = unsmob_translator_def (odef->find_translator_l (ly_car (s)));
+      Context_def *t = unsmob_context_def (odef->find_translator (ly_car (s)));
       if (!t)
        continue;
-      accepted_arr.push (t);
+      accepteds.push (t);
     }
 
-  Link_array<Translator_def> best_result;
-  for (int i=0; i < accepted_arr.size (); i++)
+  Link_array<Context_def> best_result;
+  for (int i=0; i < accepteds.size (); i++)
     {
-
       /*
        don't check aliases, because \context Staff should not create RhythmicStaff.
       */
-      if (gh_equal_p (accepted_arr[i]->type_name_, type_str))
+      if (gh_equal_p (accepteds[i]->get_context_name (), type_sym))
        {
-         best_result.push (accepted_arr[i]);
+         best_result.push (accepteds[i]);
          return best_result;
        }
     }
       
   int best_depth= INT_MAX;
-  for (int i=0; i < accepted_arr.size (); i++)
+  for (int i=0; i < accepteds.size (); i++)
     {
-      Translator_def * g = accepted_arr[i];
+      Context_def * g = accepteds[i];
 
-      Link_array<Translator_def> result
-       = g->path_to_acceptable_translator (type_str, odef);
+      Link_array<Context_def> result
+       = g->path_to_acceptable_translator (type_sym, odef);
       if (result.size () && result.size () < best_depth)
        {
          result.insert (g,0);
          best_result = result;
+
+         /*
+           this following line was added in 1.9.3, but hsould've been
+           there all along... Let's hope it doesn't cause nightmares.
+          */
+         best_depth = result.size();
        }
     }
 
   return best_result;
 }
-IMPLEMENT_UNSMOB (Translator_def,translator_def);
-IMPLEMENT_SMOBS (Translator_def);
-IMPLEMENT_DEFAULT_EQUAL_P (Translator_def);
+
+IMPLEMENT_SMOBS (Context_def);
+IMPLEMENT_DEFAULT_EQUAL_P (Context_def);
 
 
-static SCM
-trans_list (SCM namelist, Translator_group*tg)
+
+
+SCM
+Context_def::get_translator_names (SCM user_mod) const
 {
-  SCM l = SCM_EOL;
-  for (SCM s = namelist; gh_pair_p (s) ; s = ly_cdr (s))
-    {
-      Translator * t = get_translator_l (ly_scm2string (ly_car (s)));
-      if (!t)
-       warning (_f ("can't find: `%s'", s));
-      else
-       {
-         Translator * tr = t->clone ();
-         SCM str = tr->self_scm ();
-         l = gh_cons (str, l);
+  SCM l1 = SCM_EOL;
+  SCM l2 = SCM_EOL;
 
-         tr->daddy_trans_l_ = tg;
-         tr->output_def_l_  = tg->output_def_l_;
+  SCM mods = scm_reverse_x (scm_list_copy (translator_mods_),
+                           user_mod);
+  
+  for (SCM s = mods; gh_pair_p (s); s = gh_cdr (s))
+    {
+      SCM tag = gh_caar (s);
+      SCM arg = gh_cadar (s);
 
-         scm_gc_unprotect_object (str);
+      if (gh_string_p (arg))
+       arg = scm_string_to_symbol (arg);
+      
+      if (ly_symbol2scm ("consists") == tag)
+       l1 = gh_cons (arg, l1);
+      else if (ly_symbol2scm ("consists-end") == tag)
+       l2 = gh_cons (arg, l2);
+      else if (ly_symbol2scm ("remove") == tag)
+       {
+         l1 = scm_delete_x (arg, l1);
+         l2 = scm_delete_x (arg, l2);
        }
     }
-  return l; 
+
+  return scm_append_x (scm_list_2 (l1, l2));
 }
 
 
 Translator_group *
-Translator_def::instantiate (Music_output_def* md)
+Context_def::instantiate (Music_output_def* md, SCM ops)
 {
-  Translator * g = get_translator_l (ly_scm2string (translator_group_type_));
+  Translator * g = get_translator (translator_group_type_);
   g = g->clone (); 
 
   Translator_group *tg = dynamic_cast<Translator_group*> (g);
-  tg->output_def_l_ = md;
+  tg->output_def_ = md;
   tg->definition_ = self_scm ();
-  tg->type_str_ = ly_scm2string (type_name_);
-  SCM l1 = trans_list (consists_name_list_, tg);
-  SCM l2 =trans_list (end_consists_name_list_,tg);
-  l1 = scm_reverse_x (l1, l2);
-  
-  tg->simple_trans_list_ = l1;
-  
+
+  SCM trans_names = get_translator_names (ops); 
+  tg->simple_trans_list_ = names_to_translators (trans_names, tg);
+  tg->accepts_list_ = get_accepted  (ops);
   return tg;
 }
 
 
-void
-Translator_def::apply_property_operations (Translator_group*tg)
-{
-  SCM correct_order = scm_reverse (property_ops_); // pity of the mem.
-  for (SCM s = correct_order; gh_pair_p (s); s = ly_cdr (s))
-    {
-      SCM entry = ly_car (s);
-      SCM type = ly_car (entry);
-      entry = ly_cdr (entry); 
-      
-      if (type == push_sym)
-       {
-         SCM val = gh_cddr (entry);
-         val = gh_pair_p (val) ? ly_car (val) : SCM_UNDEFINED;
-
-         apply_pushpop_property (tg, ly_car (entry), gh_cadr (entry), val);
-       }
-      else if (type == assign_sym)
-       {
-         tg->set_property (ly_car (entry), gh_cadr (entry));
-       }
-    }
-}
-
 SCM
-Translator_def::clone_scm () const
+Context_def::clone_scm () const
 {
-  Translator_def * t = new Translator_def (*this);
-  return t->unprotected_smobify_self ();
+  Context_def * t = new Context_def (*this);
+  scm_gc_unprotect_object (t->self_scm());
+  return t->self_scm();
 }
 
 SCM
-Translator_def::make_scm ()
+Context_def::make_scm ()
 {
-  Translator_def* t = new Translator_def;
-  return t->unprotected_smobify_self ();
+  Context_def* t = new Context_def;
+  scm_gc_unprotect_object (t->self_scm());
+  return t->self_scm();
 }
 
 void
-Translator_def::add_property_assign (SCM nm, SCM val)
-{
-  this->property_ops_ = gh_cons (scm_list_n (assign_sym, scm_string_to_symbol (nm), val, SCM_UNDEFINED),
-                                this->property_ops_);
-}
-
-/*
-  Default child context as a SCM string, or something else if there is
-  none.
-*/
-SCM
-Translator_def::default_child_context_name ()
+Context_def::apply_default_property_operations (Translator_group *tg)
 {
-  SCM d = accepts_name_list_;
-  return gh_pair_p (d) ? ly_car (scm_last_pair (d)) : SCM_EOL;
+  apply_property_operations (tg , property_ops_);
 }
 
 SCM
-Translator_def::to_alist ()const
+Context_def::to_alist () const
 {
   SCM l = SCM_EOL;
-  
-  l = gh_cons (gh_cons (ly_symbol2scm ("consists"),  consists_name_list_), l);
-  l = gh_cons (gh_cons (ly_symbol2scm ("end-consists"),  end_consists_name_list_), l);
-  l = gh_cons (gh_cons (ly_symbol2scm ("accepts"),  accepts_name_list_), l);
+
+  l = gh_cons (gh_cons (ly_symbol2scm ("consists"),
+                       get_translator_names (SCM_EOL)), l);
+  l = gh_cons (gh_cons (ly_symbol2scm ("description"),  description_), l);
+  l = gh_cons (gh_cons (ly_symbol2scm ("aliases"),  context_aliases_), l);
+  l = gh_cons (gh_cons (ly_symbol2scm ("accepts"),  get_accepted (SCM_EOL)), l);
   l = gh_cons (gh_cons (ly_symbol2scm ("property-ops"),  property_ops_), l);
-  l = gh_cons (gh_cons (ly_symbol2scm ("type-name"),  type_name_), l); // junkme.
+  l = gh_cons (gh_cons (ly_symbol2scm ("context-name"),  context_name_), l);
   l = gh_cons (gh_cons (ly_symbol2scm ("group-type"),  translator_group_type_), l);    
 
   return l;  
 }
+
+bool
+Context_def::is_alias (SCM sym) const
+{
+  bool b  = sym == context_name_;
+
+  for (SCM a = context_aliases_; !b && gh_pair_p (a); a = ly_cdr (a))
+    b = b || sym == ly_car (a);
+
+  return b;
+}