basix_doc 0.1
|
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