On 04/12/2014, at 1:09 PM, gmhwxi wrote:
> castfn from_T3_to_T2: T3 -> T2
>
> I have never tried the first solution. I use the second one in my code.
However, just the type conversion isn't enough. You also need a
"print" routine at least for any terms for diagnostics.
For 2 or 3 variants this isn't an issue but consider this
which is the actual unbound AST term for a type in Felix (Ocaml notation):
and typecode_t =
| TYP_label
| TYP_void of Flx_srcref.t (** void type *)
| TYP_name of Flx_srcref.t * Flx_id.t * typecode_t list
| TYP_case_tag of Flx_srcref.t * int
| TYP_typed_case of Flx_srcref.t * int * typecode_t
| TYP_lookup of Flx_srcref.t * (expr_t * Flx_id.t * typecode_t list)
| TYP_index of Flx_srcref.t * string * index_t
| TYP_callback of Flx_srcref.t * qualified_name_t
| TYP_suffix of Flx_srcref.t * (qualified_name_t * typecode_t)
| TYP_patvar of Flx_srcref.t * Flx_id.t
| TYP_patany of Flx_srcref.t
| TYP_tuple of typecode_t list (** product type *)
| TYP_unitsum of int (** sum of units *)
| TYP_sum of typecode_t list (** numbered sum type *)
| TYP_intersect of typecode_t list (** intersection type *)
| TYP_record of (Flx_id.t * typecode_t) list (** anon product *)
| TYP_variant of (Flx_id.t * typecode_t) list (** anon sum *)
| TYP_function of typecode_t * typecode_t (** function type *)
| TYP_cfunction of typecode_t * typecode_t (** C function type *)
| TYP_pointer of typecode_t (** pointer type *)
| TYP_array of typecode_t * typecode_t (** array type base ^ index *)
| TYP_as of typecode_t * Flx_id.t (** fixpoint *)
| TYP_typeof of expr_t (** typeof *)
| TYP_var of index_t (** unknown type *)
| TYP_none (** unspecified *)
| TYP_ellipsis (** ... for varargs *)
(* | TYP_lvalue of typecode_t *) (** ... lvalue annotation *)
| TYP_isin of typecode_t * typecode_t (** typeset membership *)
(* sets of types *)
| TYP_typeset of typecode_t list (** discrete set of types *)
| TYP_setunion of typecode_t list (** union of typesets *)
| TYP_setintersection of typecode_t list (** intersection of typesets *)
(* dualizer *)
| TYP_dual of typecode_t (** dual *)
| TYP_apply of typecode_t * typecode_t (** type function application *)
| TYP_typefun of simple_parameter_t list * typecode_t * typecode_t
(** type lambda *)
| TYP_type (** meta type of a type *)
| TYP_type_tuple of typecode_t list (** meta type product *)
| TYP_type_match of typecode_t * (typecode_t * typecode_t) list
| TYP_type_extension of Flx_srcref.t * typecode_t list * typecode_t
| TYP_tuple_cons of Flx_srcref.t * typecode_t * typecode_t
and now here are all the unbound kinds of expressions:
and expr_t =
| EXPR_label of Flx_srcref.t * string
| EXPR_vsprintf of Flx_srcref.t * string
| EXPR_interpolate of Flx_srcref.t * string
| EXPR_map of Flx_srcref.t * expr_t * expr_t
| EXPR_noexpand of Flx_srcref.t * expr_t
| EXPR_name of Flx_srcref.t * Flx_id.t * typecode_t list
| EXPR_index of Flx_srcref.t * string * index_t
| EXPR_case_tag of Flx_srcref.t * int
| EXPR_typed_case of Flx_srcref.t * int * typecode_t
| EXPR_projection of Flx_srcref.t * int * typecode_t
| EXPR_lookup of Flx_srcref.t * (expr_t * Flx_id.t * typecode_t list)
| EXPR_apply of Flx_srcref.t * (expr_t * expr_t)
| EXPR_tuple of Flx_srcref.t * expr_t list
| EXPR_tuple_cons of Flx_srcref.t * expr_t * expr_t
| EXPR_record of Flx_srcref.t * (Flx_id.t * expr_t) list
| EXPR_record_type of Flx_srcref.t * (Flx_id.t * typecode_t) list
| EXPR_variant of Flx_srcref.t * (Flx_id.t * expr_t)
| EXPR_variant_type of Flx_srcref.t * (Flx_id.t * typecode_t) list
| EXPR_arrayof of Flx_srcref.t * expr_t list
| EXPR_coercion of Flx_srcref.t * (expr_t * typecode_t)
| EXPR_suffix of Flx_srcref.t * (qualified_name_t * typecode_t)
| EXPR_patvar of Flx_srcref.t * Flx_id.t
| EXPR_patany of Flx_srcref.t
| EXPR_void of Flx_srcref.t
| EXPR_ellipsis of Flx_srcref.t
| EXPR_product of Flx_srcref.t * expr_t list
| EXPR_sum of Flx_srcref.t * expr_t list
| EXPR_intersect of Flx_srcref.t * expr_t list
| EXPR_isin of Flx_srcref.t * (expr_t * expr_t)
| EXPR_orlist of Flx_srcref.t * expr_t list
| EXPR_andlist of Flx_srcref.t * expr_t list
| EXPR_arrow of Flx_srcref.t * (expr_t * expr_t)
| EXPR_longarrow of Flx_srcref.t * (expr_t * expr_t)
| EXPR_superscript of Flx_srcref.t * (expr_t * expr_t)
| EXPR_literal of Flx_srcref.t * Flx_literal.literal_t
| EXPR_deref of Flx_srcref.t * expr_t
| EXPR_ref of Flx_srcref.t * expr_t
| EXPR_likely of Flx_srcref.t * expr_t
| EXPR_unlikely of Flx_srcref.t * expr_t
| EXPR_new of Flx_srcref.t * expr_t
| EXPR_callback of Flx_srcref.t * qualified_name_t
| EXPR_lambda of Flx_srcref.t * (funkind_t * vs_list_t * params_t list * typecode_t * statement_t list)
| EXPR_range_check of Flx_srcref.t * expr_t * expr_t * expr_t
| EXPR_not of Flx_srcref.t * expr_t
(* this boolean expression checks its argument is
the nominated union variant .. not a very good name for it
*)
| EXPR_match_ctor of Flx_srcref.t * (qualified_name_t * expr_t)
(* this boolean expression checks its argument is the nominate
sum variant
*)
| EXPR_match_case of Flx_srcref.t * (int * expr_t)
(* this extracts the argument of a named union variant -- unsafe *)
| EXPR_ctor_arg of Flx_srcref.t * (qualified_name_t * expr_t)
(* this extracts the argument of a number sum variant -- unsafe *)
| EXPR_case_arg of Flx_srcref.t * (int * expr_t)
(* this just returns an integer equal to union or sum index *)
| EXPR_case_index of Flx_srcref.t * expr_t (* the zero origin variant index *)
| EXPR_letin of Flx_srcref.t * (pattern_t * expr_t * expr_t)
| EXPR_get_n of Flx_srcref.t * (int * expr_t)
| EXPR_get_named_variable of Flx_srcref.t * (Flx_id.t * expr_t)
| EXPR_as of Flx_srcref.t * (expr_t * Flx_id.t)
| EXPR_as_var of Flx_srcref.t * (expr_t * Flx_id.t)
| EXPR_match of Flx_srcref.t * (expr_t * (pattern_t * expr_t) list)
(* this extracts the tail of a tuple *)
| EXPR_get_tuple_tail of Flx_srcref.t * expr_t
| EXPR_get_tuple_head of Flx_srcref.t * expr_t
| EXPR_typeof of Flx_srcref.t * expr_t
| EXPR_cond of Flx_srcref.t * (expr_t * expr_t * expr_t)
| EXPR_expr of Flx_srcref.t * string * typecode_t
| EXPR_type_match of Flx_srcref.t * (typecode_t * (typecode_t * typecode_t) list)
| EXPR_extension of Flx_srcref.t * expr_t list * expr_t
we also have patterns, statements, a subset of the statement which
are executable instructions ...
Apart from printing all these terms, there are also functions to find
the original source location (in the users file), iterators, and maps.
And this is just the raw input AST, which then goes through several
transformations until we end up with bound terms (ones where
string names are replaced by referenced to the symbol to which they
refer, i.e. with lookup done). Then the bound terms go through several
optimisation, transformation and reduction processes. Because my compiler
translates to C++ things one would normally erase, such as source locations
and type information, have to be retained all the way through.
So some way to have a term such as those above with constraints that
can change as we go through some process .. without having to use a new
type for it, and thereby not only make a slightly modified copy of the term, but
also a new printing function, a new iterator, a new mapper ... would seem
ideal (for this particular task).
As it is I often write checking functions for the constraints, but this sucks
compared to static typing.