basix_doc 0.1
/Users/mourrain/Devel/mmx/basix/glue/glue_list_map.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : list_glue.cpp
00004 * DESCRIPTION: Standard glue for lists
00005 * COPYRIGHT  : (C) 2006  Joris van der Hoeven
00006 *******************************************************************************
00007 * This software falls under the GNU general public license and comes WITHOUT
00008 * ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
00009 * If you don't have this file, write to the Free Software Foundation, Inc.,
00010 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00011 ******************************************************************************/
00012 
00013 #include <basix/list.hpp>
00014 #include <basix/list_sort.hpp>
00015 #include <basix/tuple.hpp>
00016 #include <basix/glue.hpp>
00017 #include <basix/routine.hpp>
00018 namespace mmx {
00019 
00020 template<typename T> vector<T>
00021 as_vector (const list<T>& l) {
00022   vector<T> a (fill<T> (N (l)));
00023   list<T> it= l;
00024   for (nat i= 0; !is_nil (it); it= cdr (it), i++)
00025     a[i]= car (it);
00026   return a;
00027 }
00028 
00029 static generic
00030 rebuild (const list<generic>& l) {
00031   generic make_list= eval ("list");
00032   return as<routine> (make_list) -> apply (as_vector<generic> (l));
00033 }
00034 
00035 list<generic>
00036 list_map_1 (const routine& fun, const list<generic>& l) {
00037   if (is_nil (l)) return l;
00038   generic r= fun->apply (car (l));
00039   return cons (r, list_map_1 (fun, cdr (l)));
00040 }
00041 
00042 list<generic>
00043 list_map_2 (const routine& fun,
00044             const list<generic>& l1, const list<generic>& l2)
00045 {
00046   ASSERT (is_nil (l1) == is_nil (l2), "lists of unequal lengths");
00047   if (is_nil (l1)) return l1;
00048   generic r= fun->apply (car (l1), car (l2));
00049   return cons (r, list_map_2 (fun, cdr (l1), cdr (l2)));
00050 }
00051 
00052 list<generic>
00053 list_map_n (const routine& fun, const vector<list<generic> >& a) {
00054   nat i, n= N(a);
00055   vector<generic> cara= fill<generic> (n);
00056   if (is_nil (a[0])) {
00057     for (i=0; i<n; i++)
00058       ASSERT (is_nil (a[i]), "lists of unequal lengths");
00059     return a[0];
00060   }
00061   for (i=0; i<n; i++) {
00062     ASSERT (!is_nil (a[i]), "lists of unequal lengths");
00063     cara[i]= car (a[i]);
00064   }
00065   vector<list<generic> > cdra= fill<list<generic> > (n);
00066   for (i=0; i<n; i++) cdra[i]= cdr (a[i]);
00067   generic r= fun->apply (cara);
00068   return cons (r, list_map_n (fun, cdra));
00069 }
00070 
00071 generic
00072 list_map (const generic& f, const tuple<list<generic> >& t) {
00073   routine fun= is<routine> (f)? as<routine> (f): default_routine (f);
00074   switch (N(t)) {
00075   case 0: ASSERT (N(t)>0, "wrong number of arguments");
00076   case 1: return rebuild (list_map_1 (fun, t[0]));
00077   case 2: return rebuild (list_map_2 (fun, t[0], t[1]));
00078   default:
00079     {
00080       const vector<generic> a= cdr (compound_to_vector (*t));
00081       nat i, n= N(a);
00082       vector<list<generic> > b= fill<list<generic> > (n);
00083       for (i=0; i<n; i++) b[i]= as<list<generic> > (a[i]);
00084       return rebuild (list_map_n (fun, b));
00085     }
00086   }
00087 }
00088 
00089 generic
00090 list_foreach (const generic& f, const tuple<list<generic> >& t) {
00091   generic r= list_map (f, t);
00092   return as<generic> (tuple<generic> (gen (GEN_TUPLE)));
00093 }
00094 
00095 generic
00096 list_append_several (const tuple<list<generic> >& t) {
00097   list<generic> r;
00098   for (int i=N(t)-1; i>=0; i--)
00099     r= t[i] * r;
00100   return rebuild (r);
00101 }
00102 
00103 generic
00104 list_apply (const generic& f, const list<generic>& l2) {
00105   routine fun= is<routine> (f)? as<routine> (f): default_routine (f);
00106   list<generic> l= l2;
00107   nat i, n= N(l);
00108   vector<generic> a= fill<generic> (n);
00109   for (i=0; !is_nil (l); i++, l= read_cdr(l))
00110     a[i]= read_car (l);
00111   return fun->apply (a);
00112 }
00113 
00114 static routine current_comparison;
00115 
00116 static int
00117 generic_compare (const generic& x, const generic& y) {
00118   bool b= as<bool> (current_comparison->apply (x, y));
00119   return b? -1: 1;
00120 }
00121 
00122 list<generic>
00123 list_sort (const list<generic>& l, const generic& f) {
00124   routine old_comparison= current_comparison;
00125   current_comparison= is<routine> (f)? as<routine> (f): default_routine (f);
00126   list<generic> r= sort (l, generic_compare);
00127   current_comparison= old_comparison;
00128   return r;
00129 }
00130 
00131 /*
00132 list<generic>
00133 list_filter_bis (const list<generic>& l, const routine& fun) {
00134   if (is_nil (l)) return l;
00135   generic cond= fun->apply (car (l));
00136   if (is<bool> (cond) && as<bool> (cond))
00137     return cons (car (l), list_filter_bis (cdr (l), fun));
00138   else return list_filter_bis (cdr (l), fun);
00139 }
00140 
00141 generic
00142 list_filter (const list<generic>& l, const routine& fun) {
00143   return rebuild (list_filter_bis (l, fun));
00144 }
00145 
00146 generic
00147 list_find_index (const list<generic>& l2, const routine& fun) {
00148   int i= 0;
00149   list<generic> l= l2;
00150   while (!is_nil (l)) {
00151     generic cond= fun->apply (car (l));
00152     if (is<bool> (cond) && as<bool> (cond)) return as<generic> (i);
00153     i++; l= cdr (l);
00154   }
00155   return as<generic> (false);
00156 }
00157 */
00158 
00159 void
00160 glue_list_map () {
00161   static bool done = false;
00162   if (done) return;
00163   done = true;
00164   register_glue ("glue_list_map", &glue_list_map);
00165   call_glue ("glue_list_generic");
00166   define ("map", list_map);
00167   define ("foreach", list_foreach);
00168   define ("append", list_append_several);
00169   define ("apply", list_apply);
00170   define ("sort", list_sort);
00171   //define ("filter", list_filter);
00172   //define ("find_index", list_find_index);
00173 }
00174 
00175 } // namespace mmx
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines