00001 /* Part of the culibs project, <http://www.eideticdew.org/culibs/>. 00002 * Copyright (C) 2004--2007 Petter Urkedal <urkedal@nbi.dk> 00003 * 00004 * This program is free software: you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation, either version 3 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 */ 00017 00018 #ifndef CHI_LO_SUBST_H 00019 #define CHI_LO_SUBST_H 00020 00021 #include <cuex/fwd.h> 00022 #include <cuex/pvar.h> 00023 #include <cucon/pmap.h> 00024 #include <cucon/slink.h> 00025 #include <cufo/fwd.h> 00026 #include <cu/conf.h> 00027 #include <stdio.h> 00028 00029 CU_BEGIN_DECLARATIONS 00030 /*!\defgroup cuex_subst_h cuex/subst.h: Substitutions 00031 * @{ \ingroup cuex_mod 00032 * Substitutions are here implemented as maps from variables to equivalence 00033 * sets of variables and value-expressions. A \ref cuex_subst 00034 * "cuex_subst_t" has a specified set of active quantification kinds. \ref 00035 * cuex_subst_unify will attempt to extend the substitution so as to unify two 00036 * expressions by adding bindings for variables with active quantification. 00037 * Unification can produce variable equivalences of the form \e x = \e y where 00038 * \e x and \e y are variables, or bindings of the form \e x = \e e where \e e 00039 * is an expression. This is handled by mapping each variable \e x to (\e S, 00040 * \e e), where \e S is the set of \e x and all variables equivalent to it and 00041 * \e e is an optional binding for all variables in \e S. (\e S, \e e) is 00042 * represented by \ref cuex_veqv and is shared between variables in \e S. 00043 */ 00044 00045 /*!An equivalence set of variables with an optional binding. This is only 00046 * used as part of a \ref cuex_subst. */ 00047 struct cuex_veqv 00048 { 00049 unsigned int qcode : 8; /* Actual type is cuex_qcode_t. */ 00050 cu_bool_t is_feedback_var : 1; 00051 cucon_slink_t var_link; 00052 cuex_t value; 00053 }; 00054 00055 typedef cucon_slink_t cuex_veqv_it_t; 00056 00057 /** The quantification of variables in \a vq. */ 00058 CU_SINLINE cuex_qcode_t 00059 cuex_veqv_qcode(cuex_veqv_t vq) { return (cuex_qcode_t)vq->qcode; } 00060 00061 /*!The value of variables in \a vq or \c NULL if unknown. */ 00062 CU_SINLINE cuex_t cuex_veqv_value(cuex_veqv_t vq) { return vq->value; } 00063 00064 /*!The primary variable of \a vq. */ 00065 CU_SINLINE cuex_var_t cuex_veqv_primary_var(cuex_veqv_t vq) 00066 { return (cuex_var_t)cucon_slink_get_ptr(vq->var_link); } 00067 00068 /*!After calling \ref cuex_subst_mark_min_feedback or \ref 00069 * cuex_subst_mark_all_feedback, and before any further change to the 00070 * substitution, this will return true iff the variables of \a vq are part of 00071 * a minimum feedback set or which are strongly connected, rsp. Useful only 00072 * for non-idempotent substitutions. */ 00073 CU_SINLINE cu_bool_t cuex_veqv_is_feedback(cuex_veqv_t vq) 00074 { return vq->is_feedback_var; } 00075 00076 /*!An iterator to the first variable in \a vq. */ 00077 CU_SINLINE cuex_veqv_it_t cuex_veqv_begin(cuex_veqv_t vq) 00078 { return vq->var_link; } 00079 00080 /*!An iterator beyond the range of variables in \a vq. */ 00081 CU_SINLINE cuex_veqv_it_t cuex_veqv_end(cuex_veqv_t vq) { return NULL; } 00082 00083 /*!The iterator next after \a it in a range of variables. */ 00084 CU_SINLINE cuex_veqv_it_t cuex_veqv_it_next(cuex_veqv_it_t it) 00085 { return cucon_slink_next(it); } 00086 00087 /*!The variable at \a it. */ 00088 CU_SINLINE cuex_var_t cuex_veqv_it_get(cuex_veqv_it_t it) 00089 { return (cuex_var_t)cucon_slink_get_ptr(it); } 00090 00091 /*!The representation of a substitution. */ 00092 struct cuex_subst 00093 { 00094 size_t clone_cnt; 00095 size_t shadow_access_cnt; 00096 cuex_subst_t shadowed; 00097 struct cucon_pmap var_to_veqv; 00098 unsigned int qcset : 8; /* Actual type is cuex_qcset_t. */ 00099 cu_bool_least_t is_idem; 00100 }; 00101 00102 /*!Construct \a subst where variables of quantisation in \a qcset are 00103 * unifiable (substitutable). */ 00104 void cuex_subst_init(cuex_subst_t subst, cuex_qcset_t qcset); 00105 00106 void cuex_subst_init_nonidem(cuex_subst_t subst, cuex_qcset_t qcset); 00107 00108 CU_SINLINE void cuex_subst_init_uw(cuex_subst_t subst) 00109 { cuex_subst_init(subst, cuex_qcset_uw); } 00110 CU_SINLINE void cuex_subst_init_e(cuex_subst_t subst) 00111 { cuex_subst_init(subst, cuex_qcset_e); } 00112 CU_SINLINE void cuex_subst_init_n(cuex_subst_t subst) 00113 { cuex_subst_init(subst, cuex_qcset_n); } 00114 00115 /*!Return a substitution with \a qcset as the quantisation of 00116 * variables which are substitutable. */ 00117 cuex_subst_t cuex_subst_new(cuex_qcset_t qcset); 00118 00119 cuex_subst_t cuex_subst_new_nonidem(cuex_qcset_t qcset); 00120 00121 CU_SINLINE cuex_subst_t cuex_subst_new_uw(void) 00122 { return cuex_subst_new(cuex_qcset_uw); } 00123 CU_SINLINE cuex_subst_t cuex_subst_new_e(void) 00124 { return cuex_subst_new(cuex_qcset_e); } 00125 CU_SINLINE cuex_subst_t cuex_subst_new_n(void) 00126 { return cuex_subst_new(cuex_qcset_n); } 00127 00128 /*!Return a shallow copy of \a src_subst, which may be NULL. */ 00129 cuex_subst_t cuex_subst_new_clone(cuex_subst_t src_subst, cuex_qcset_t qcset); 00130 CU_SINLINE cuex_subst_t cuex_subst_new_uw_clone(cuex_subst_t src_subst) 00131 { return cuex_subst_new_clone(src_subst, cuex_qcset_uw); } 00132 CU_SINLINE cuex_subst_t cuex_subst_new_e_clone(cuex_subst_t src_subst) 00133 { return cuex_subst_new_clone(src_subst, cuex_qcset_e); } 00134 CU_SINLINE cuex_subst_t cuex_subst_new_n_clone(cuex_subst_t src_subst) 00135 { return cuex_subst_new_clone(src_subst, cuex_qcset_n); } 00136 00137 /*!Return a deep copy of \a subst. */ 00138 cuex_subst_t cuex_subst_new_copy(cuex_subst_t src_subst); 00139 00140 CU_SINLINE cuex_qcset_t cuex_subst_active_qcset(cuex_subst_t subst) 00141 { return (cuex_qcset_t)subst->qcset; } 00142 00143 CU_SINLINE cu_bool_t 00144 cuex_subst_is_active_varmeta(cuex_subst_t subst, cuex_meta_t varmeta) 00145 { return cuex_qcset_contains(cuex_subst_active_qcset(subst), 00146 cuex_varmeta_qcode(varmeta)); } 00147 00148 /*!Merge all relevant bindings from inherited substitutions of \a subst into 00149 * \a subst, and drop the inheritance. */ 00150 void cuex_subst_flatten(cuex_subst_t subst); 00151 00152 /*!Indicate that \a subst is no longer in use. This is just an optimisation, 00153 * you never need to call this. */ 00154 void cuex_subst_delete(cuex_subst_t subst); 00155 00156 /*!The number of variables in \a subst, possible counting variables which 00157 * have been shadowed after cloning and modifying a substitution. For 00158 * cloned substitutions this is just for estimation, since 00159 * treatment of shadowing is inherently unpredictable. */ 00160 size_t cuex_subst_size(cuex_subst_t subst); 00161 00162 cuex_veqv_t cuex_subst_cref(cuex_subst_t subst, cuex_var_t var); 00163 cuex_veqv_t cuex_subst_mref(cuex_subst_t subst, cuex_var_t var); 00164 00165 /*!True iff \a subst is the identity substitution. */ 00166 cu_bool_t cuex_subst_is_identity(cuex_subst_t subst); 00167 00168 /*!Attempt to unify \a ex0 and \a ex1 while respecting and adding new variable 00169 * unifications in \a subst. If both \a ex0 and \a ex1 are valueless 00170 * variables, the primary variable of \a ex1 is preserved. */ 00171 cu_bool_t cuex_subst_unify(cuex_subst_t subst, cuex_t ex0, cuex_t ex1); 00172 00173 /*!\copydoc cuex_subst_unify 00174 * Whenever unification fails for pair of subexpressions, the 00175 * result of \a aux_unify is used instead. */ 00176 cuex_t 00177 cuex_subst_unify_aux(cuex_subst_t subst, cuex_t ex0, cuex_t ex1, 00178 cu_clop(aux_unify, cuex_t, cuex_subst_t, cuex_t, cuex_t)); 00179 00180 /*!Block \a v from being unified with non-variables. */ 00181 void cuex_subst_block(cuex_subst_t subst, cuex_var_t v); 00182 00183 /*!Remove a unification-block of \a v. */ 00184 void cuex_subst_unblock(cuex_subst_t subst, cuex_var_t v); 00185 00186 /*!Remove all unification-blocks for variables in \a subst. */ 00187 void cuex_subst_unblock_all(cuex_subst_t subst); 00188 00189 /*!For each variable in \a ex which does not have a mapping, insert a 00190 * substitution from it to a fresh blocked variable. */ 00191 void cuex_subst_freshen_and_block_vars_in(cuex_subst_t subst, cuex_t ex); 00192 00193 /* Insert all veqvs in \a ex into \a veqvset. */ 00194 void cuex_subst_collect_veqvset(cuex_subst_t subst, cuex_t ex, 00195 cucon_pmap_t veqvset); 00196 00197 /*!Return the mapping of \a var in \a subst. If there is no mapping to 00198 * non-variables, return the primary variable. */ 00199 cuex_t cuex_subst_lookup(cuex_subst_t subst, cuex_var_t var); 00200 00201 /*!Return the application of \a subst to \a ex. 00202 * \pre \a subst is idempotent. */ 00203 cuex_t cuex_subst_apply(cuex_subst_t subst, cuex_t ex); 00204 00205 /*!Update each <tt>cuex_tvar_t</tt> type in \a ex to the result of applying 00206 * \a subst to it. */ 00207 void cuex_subst_update_tvar_types(cuex_subst_t subst, cuex_t ex); 00208 00209 /*!Return \a ex with a single expansion of variabels from \a subst. This 00210 * also works for non-idempotent substitutions. */ 00211 cuex_t cuex_subst_expand(cuex_subst_t subst, cuex_t ex); 00212 00213 /*!Call \a cb for each \a veqv in \a subst. */ 00214 void cuex_subst_iter_veqv(cuex_subst_t subst, cu_clop(cb, void, cuex_veqv_t)); 00215 00216 /*!Call \a f for each \a veqv in \a subst. To each \c cuex_veqv_t a unique 00217 * cache slot of \a cache_size bytes is passed to \a f. \a f may request the 00218 * cache data of another variable to be computed before returing, but calling 00219 * \ref cuex_subst_iter_veqv_cache_sub on the provided \a sub_data. 00220 * \see cuex_subst_tran_cache */ 00221 void cuex_subst_iter_veqv_cache(cuex_subst_t subst, size_t cache_size, 00222 cu_clop(f, void, cuex_veqv_t veqv, void *cache, 00223 void *sub_data)); 00224 /*!This is used only inside the callback of \ref cuex_subst_iter_veqv_cache. 00225 * It forces a computation of cache data for \a var before finishing the 00226 * current callback. It is unsafe to use this on non-idempotent 00227 * substitutions. */ 00228 void *cuex_subst_iter_veqv_cache_sub(void *sub_data, cuex_t var); 00229 00230 /*!Transform all bindings in \a subst with \a f. \a f is passed a cache of \a 00231 * cache_size bytes, where it can store auxiliary data used during the 00232 * computation. The cache associated with a set of equivalent variables can 00233 * be queried with \ref cuex_subst_tran_cache_sub, which will force the given 00234 * variable to be processed if necessary. 00235 * \see cuex_subst_iter_veqv_cache */ 00236 cuex_subst_t 00237 cuex_subst_tran_cache(cuex_subst_t subst, size_t cache_size, 00238 cu_clop(f, cuex_t, cuex_t value, void *cache, 00239 void *sub_data)); 00240 00241 /*!This is used only inside the callback of \a cuex_subst_tran_cache. It 00242 * forces a computation of cache data for \a var. It is unsafe to use this on 00243 * non-idempotent substitutions. */ 00244 void *cuex_subst_tran_cache_sub(void *sub_data, cuex_t var); 00245 00246 /*!Sequentially conjunct \a cb over variables that would be left after 00247 * applying \a subst to \a ex. For variables in \a ex which are part of an 00248 * equavalence, \a cb is called with the primary variable. 00249 * \see cuex_subst_free_vars_insert, cuex_subst_free_vars_erase */ 00250 cu_bool_t cuex_subst_free_vars_conj(cuex_subst_t subst, cuex_t ex, 00251 cu_clop(cb, cu_bool_t, cuex_var_t)); 00252 00253 /*!Insert each variable that would be left after applying \a subst to \a ex 00254 * into \a accu. 00255 * \see cuex_subst_free_vars_conj */ 00256 void cuex_subst_free_vars_insert(cuex_subst_t subst, cuex_t ex, 00257 cucon_pset_t accu); 00258 00259 /*!Erase each variable that would be left after applying \a subst to \a ex 00260 * from \a accu. 00261 * \see cuex_subst_free_vars_conj */ 00262 void cuex_subst_free_vars_erase(cuex_subst_t subst, cuex_t ex, 00263 cucon_pset_t accu); 00264 00265 /*!Print \a subst to \a file, using \a sep to separate elements. */ 00266 void cuex_subst_print(cuex_subst_t subst, cufo_stream_t fos, char const *sep); 00267 00268 /*!Debug dump of \a subst. */ 00269 void cuex_subst_dump(cuex_subst_t subst, FILE *file); 00270 00271 00272 /* Algorithms 00273 * ---------- */ 00274 00275 /* For each node of 'ex', create a mapping to a node which is 00276 * equivalent under 'dst' where its subexpressions are replaced by 00277 * appropriate variables. Returns the variable which is equivalent to 00278 * 'ex' under 'dst'. 'ex_to_var' shall be a mapping from expressions 00279 * to variables, and may be empty or contain accumulation from 00280 * previous calls. Variabels in 'ex' are resolved using 'src'. */ 00281 cuex_var_t cuex_subst_insert_fragment_accum(cuex_subst_t dst, 00282 cucon_pmap_t ex_to_var, 00283 cuex_t ex, cuex_subst_t src); 00284 00285 /* Calls the above with an empty 'ex_to_var'. */ 00286 cuex_var_t cuex_subst_insert_expand(cuex_subst_t dst, 00287 cuex_t ex, cuex_subst_t src); 00288 00289 /* Return a substitution which defines the cuex_var_t keys of 00290 * 'var_to_var' equivalently, but maximally expanded using 00291 * 'cuex_subst_insert_fragment_accum', and set the cuex_var_t slots of 00292 * 'var_to_var' to the variables corresponding to the keys. */ 00293 cuex_subst_t cuex_subst_fragment_project(cuex_subst_t subst, 00294 cucon_pmap_t var_to_var); 00295 00296 #ifdef CUCONF_HAVE_BUDDY 00297 /*!Return an idempotent rewrite of the possibly non-idempotent \a subst. 00298 * Mutually recursive bindings are replaced by bindings to a top-level \ref 00299 * CUEX_O2_RBIND where the LHS is a \a CUEX_OR_TUPLE of the old 00300 * bindings with back-refereces replaced with appropriate \a cuex_rvar_t 00301 * variables, and the RHS is the \a cuex_rvar_t selecting the appropriate 00302 * component. 00303 * \note Only avaliable if built with BuDDY. 00304 * \see cuex_subst_mark_min_feedback */ 00305 void cuex_subst_render_idempotent(cuex_subst_t subst); 00306 00307 /*!Mark all \ref cuex_veqv "cuex_veqv_t" nodes of \a subst which are part of 00308 * a minimum feedback variable set. The marks can be inspected with \ref 00309 * cuex_veqv_is_feedback. 00310 * \note Only available if built with BuDDY. 00311 * \see cuex_subst_mark_all_feedback 00312 * \see cuex_subst_render_idempotent */ 00313 cu_bool_t cuex_subst_mark_min_feedback(cuex_subst_t subst); 00314 00315 /*!Mark all \ref cuex_veqv "cuex_veqv_t" nodes of \a subst which are part of 00316 * a circular dependency. Considering \a subst to be a directed graph, this 00317 * marks all strongly connected nodes. The marks can be inspected with \ref 00318 * cuex_veqv_is_feedback. 00319 * \note Only available if built with BuDDY. 00320 * \see cuex_subst_mark_min_feedback 00321 * \see cuex_subst_render_idempotent */ 00322 cu_bool_t cuex_subst_mark_all_feedback(cuex_subst_t subst); 00323 #endif 00324 00325 /*!@}*/ 00326 #define cuex_subst_cct cuex_subst_init 00327 #define cuex_subst_cct_nonidem cuex_subst_init_nonidem 00328 #define cuex_subst_cct_uw cuex_subst_init_uw 00329 #define cuex_subst_cct_e cuex_subst_init_e 00330 #define cuex_subst_cct_n cuex_subst_init_n 00331 CU_END_DECLARATIONS 00332 00333 #endif