00001 /* Part of the culibs project, <http://www.eideticdew.org/culibs/>. 00002 * Copyright (C) 2006--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 CUEX_TPVAR_H 00019 #define CUEX_TPVAR_H 00020 00021 #include <cuex/fwd.h> 00022 #include <cuex/var.h> 00023 #include <cu/int.h> 00024 00025 CU_BEGIN_DECLARATIONS 00026 /*!\defgroup cuex_tpvar_h cuex/tpvar.h: Parametric Type Variables 00027 * @{\ingroup cuex_mod 00028 * Type parameter variables meant for representing Hindley-Milner style type 00029 * parameters with size information and optional links to type classes. They 00030 * are hash-consed based on an index (and two more arguments), so as to 00031 * facilitate cannonical representations of parametric expressions. 00032 * 00033 * A typical use for this is to represent definitions of the form 00034 * <pre> 00035 * α list = nil | cons of α × α list (a type) 00036 * image : (α → β → β) → α list → β → β (a function) 00037 * </pre> 00038 * where the greek letters denote universally quantised type parameters. 00039 * 00040 * These variables have an associated width mask, which stores all possible 00041 * widths of the parametric type for which the definition shall be 00042 * instantiated. Bit number \e n indicates whether the width 2↑\e n is 00043 * supported by the definition. It is implied here that the caller will cast 00044 * values of a given width to the closest bigger supported with, or if none is 00045 * available, pass the value as a pointer. Therefore, the bit corresponding to 00046 * the width of a pointer (bit 5 or 6 for 32 or 64 bit architectures, 00047 * respectively) should always be set. It is further implied that a parametric 00048 * function only deals with objects of a parametric type opaquely, which is 00049 * the case for ML-style parametric functions. 00050 * 00051 * A way to go beyond the opaque treatment of parametrically typed objects, is 00052 * to introduce type-classes. Therefore, a final type class argument is passed 00053 * to the hash-constructor. We make no assumption about how this is 00054 * represented except that it must be an expression to allow client code to 00055 * check its type at runtime. You can embed any structure in an expression, 00056 * just make an opaque type for it. 00057 * 00058 * A way to achieve a cannonical representation is to start indexing from the 00059 * innermost expressions, re-using indexes for parallel definitions, and using 00060 * higher indices for enclosing expressions. */ 00061 00062 #define cuex_tpvarmeta(index) \ 00063 cuex_varmeta_kqis(cuex_varkind_tpvar, cuex_qcode_u, 0, \ 00064 (sizeof(struct cuex_tpvar) - CUOO_HCOBJ_SHIFT) \ 00065 / sizeof(cu_word_t)) 00066 #define cuex_is_tpvarmeta(meta) \ 00067 cuex_is_varmeta_k(meta, cuex_varkind_tpvar) 00068 00069 struct cuex_tpvar 00070 { 00071 CUOO_HCOBJ 00072 cu_offset_t width_mask; 00073 cuex_t type_class; 00074 }; 00075 00076 /*!Hash-cons a variable based on the arguments. If \a type_class is unused, 00077 * set it to \c NULL. */ 00078 cuex_tpvar_t cuex_tpvar(int index, cu_offset_t width_mask, cuex_t type_class); 00079 00080 /*!The index of \a alpha. */ 00081 CU_SINLINE int cuex_tpvar_index(cuex_tpvar_t alpha) 00082 { return cuex_varmeta_index(cuex_meta(alpha)); } 00083 00084 /*!The width mask of \a alpha. For each bit set, the quantified definition 00085 * shall be specialised for the width 2↑\e n where \e n is the bit number. */ 00086 CU_SINLINE cu_offset_t cuex_tpvar_width_mask(cuex_tpvar_t alpha) 00087 { return alpha->width_mask; } 00088 00089 /*!The number of widths for which this type parameter shall be specialised. */ 00090 CU_SINLINE int cuex_tpvar_width_count(cuex_tpvar_t alpha) 00091 { return CU_OFFSET_NAME(cu_, bit_count)(alpha->width_mask); } 00092 00093 /*!The type class of \a alpha, or \c NULL if none. */ 00094 CU_SINLINE cuex_t cuex_tpvar_type_class(cuex_tpvar_t alpha) 00095 { return alpha->type_class; } 00096 00097 /*!@}*/ 00098 CU_END_DECLARATIONS 00099 00100 #endif