Data Structures | |
struct | cuex_tpvar |
Defines | |
#define | cuex_tpvarmeta(index) |
#define | cuex_is_tpvarmeta(meta) cuex_is_varmeta_k(meta, cuex_varkind_tpvar) |
Functions | |
cuex_tpvar_t | cuex_tpvar (int index, cu_offset_t width_mask, cuex_t type_class) |
int | cuex_tpvar_index (cuex_tpvar_t alpha) |
cu_offset_t | cuex_tpvar_width_mask (cuex_tpvar_t alpha) |
int | cuex_tpvar_width_count (cuex_tpvar_t alpha) |
cuex_t | cuex_tpvar_type_class (cuex_tpvar_t alpha) |
Type parameter variables meant for representing Hindley-Milner style type parameters with size information and optional links to type classes. They are hash-consed based on an index (and two more arguments), so as to facilitate cannonical representations of parametric expressions.
A typical use for this is to represent definitions of the form
α list = nil | cons of α × α list (a type) image : (α → β → β) → α list → β → β (a function)
where the greek letters denote universally quantised type parameters.
These variables have an associated width mask, which stores all possible widths of the parametric type for which the definition shall be instantiated. Bit number n indicates whether the width 2↑n is supported by the definition. It is implied here that the caller will cast values of a given width to the closest bigger supported with, or if none is available, pass the value as a pointer. Therefore, the bit corresponding to the width of a pointer (bit 5 or 6 for 32 or 64 bit architectures, respectively) should always be set. It is further implied that a parametric function only deals with objects of a parametric type opaquely, which is the case for ML-style parametric functions.
A way to go beyond the opaque treatment of parametrically typed objects, is to introduce type-classes. Therefore, a final type class argument is passed to the hash-constructor. We make no assumption about how this is represented except that it must be an expression to allow client code to check its type at runtime. You can embed any structure in an expression, just make an opaque type for it.
A way to achieve a cannonical representation is to start indexing from the innermost expressions, re-using indexes for parallel definitions, and using higher indices for enclosing expressions.
#define cuex_tpvarmeta | ( | index | ) |
cuex_varmeta_kqis(cuex_varkind_tpvar, cuex_qcode_u, 0, \ (sizeof(struct cuex_tpvar) - CUOO_HCOBJ_SHIFT) \ / sizeof(cu_word_t))
cuex_tpvar_t cuex_tpvar | ( | int | index, | |
cu_offset_t | width_mask, | |||
cuex_t | type_class | |||
) |
Hash-cons a variable based on the arguments. If type_class is unused, set it to NULL
.
int cuex_tpvar_index | ( | cuex_tpvar_t | alpha | ) |
The index of alpha.
cuex_t cuex_tpvar_type_class | ( | cuex_tpvar_t | alpha | ) |
The type class of alpha, or NULL
if none.
int cuex_tpvar_width_count | ( | cuex_tpvar_t | alpha | ) |
The number of widths for which this type parameter shall be specialised.
cu_offset_t cuex_tpvar_width_mask | ( | cuex_tpvar_t | alpha | ) |
The width mask of alpha. For each bit set, the quantified definition shall be specialised for the width 2↑n where n is the bit number.