


## highcode-type.api
#
# Here and in
#
# src/lib/compiler/back/top/highcode/highcode-type.pkg#
# we implement the client-code interface to the
# hash-consed types implemented in
#
# src/lib/compiler/back/top/highcode/highcode-uniq-types.pkg#
# For general context, see
#
# src/A.COMPILER.OVERVIEW
#
# For authoritative background see Zhong Shao's PhD thesis:
#
# Compiling Standard ML for Efficient Execution on Modern Machines
# http://flint.cs.yale.edu/flint/publications/zsh-thesis.html
#
# Here we implement what his thesis calls LTY ("LEXP types").
#
# These type representations are used in all
# three of the intermediate code representations
# used in the upper half, namely lambdacode (polymorphically typed lambda calculus),
# anormcode (A-Normal format) and nextcode ("continuation passing style"):
#
# src/lib/compiler/back/top/anormcode/anormcode-form.pkg# src/lib/compiler/back/top/lambdacode/lambdacode-form.pkg# src/lib/compiler/back/top/nextcode/nextcode-form.api#
# This interface hides the implementation details of highcode
# Uniqkind, Uniqtyp, and Uniqtype defined inside
# highcode_uniq_types. The main point of this is to shield our code
# clients from the complexity of the hash-consing which we
# implement in
#
# src/lib/compiler/back/top/highcode/highcode-uniq-types.pkg#
# For each entity, we provide a series of constructor functions,
# deconstructor functions, predicate functions, and
# functions that test equivalence and do pretty-printing.
#
# This interface should only refer to packages
# debruijn_index
# highcode_uniq_types,
# highcode_basetypes
# symbol
# Compiled by:
# src/lib/compiler/core.sublib### "Once code is decently formatted
### and commented, sometimes even the
### original author can understand it."
###
### Wilbur Thompson
stipulate
package di = debruijn_index; # debruijn_index is from src/lib/compiler/front/typer/basics/debruijn-index.pkg package hbt = highcode_basetypes; # highcode_basetypes is from src/lib/compiler/back/top/highcode/highcode-basetypes.pkg package hut = highcode_uniq_types; # highcode_uniq_types is from src/lib/compiler/back/top/highcode/highcode-uniq-types.pkg package tmp = highcode_codetemp; # highcode_codetemp is from src/lib/compiler/back/top/highcode/highcode-codetemp.pkg package hbt = highcode_basetypes; # highcode_basetypes is from src/lib/compiler/back/top/highcode/highcode-basetypes.pkgherein
# This api is implemented in:
#
# src/lib/compiler/back/top/highcode/highcode-type.pkg api Highcode_Type {
#
#
# Background: Values, Types and Kinds
#
# types are sets of values
# kinds are sets of types
#
# For example
#
# Bool = TRUE | FALSE; # A type.
# 'Scalar' = Bool | Int | Float; # A kind.
#
# The Mythryl surface language has values and types but not kinds,
# but within the compiler we need all three.
# Anormcode Highcode_Kind is roughly equivalent to the following Mythryl datatype
#
# Kind
# = TYPE
# | BOXED_TYPE
# | TYPESEQ List(Uniqkind)
# | TYPEFUN (Uniqkind, Uniqkind)
# ;
#
# We treat Uniqkind as an abstract type
# to isolate clients from the complexity of the
# hashconsing machinery; this has the downside
# of preventing them from using pattern matching.
# Uniqkind constructors.
#
# The first two are just global constants:
#
plaintype_uniqkind: hut::Uniqkind;
boxedtype_uniqkind: hut::Uniqkind;
make_kindseq_uniqkind: List(hut::Uniqkind) -> hut::Uniqkind;
make_kindfun_uniqkind: (List(hut::Uniqkind), hut::Uniqkind) -> hut::Uniqkind;
# Uniqkind deconstructors -- inverses to above four.
#
# The first two here are basically useless;
# they just "complete the set".
#
unpack_plaintype_uniqkind: hut::Uniqkind -> Void; # fn _ = ();
unpack_boxedtype_uniqkind: hut::Uniqkind -> Void; # fn _ = ();
unpack_kindseq_uniqkind: hut::Uniqkind -> List(hut::Uniqkind);
unpack_kindfun_uniqkind: hut::Uniqkind -> (List(hut::Uniqkind), hut::Uniqkind);
# Uniqkind predicates:
#
uniqkind_is_plaintype: hut::Uniqkind -> Bool;
uniqkind_is_boxedtype: hut::Uniqkind -> Bool;
uniqkind_is_kindseq: hut::Uniqkind -> Bool;
uniqkind_is_kindfun: hut::Uniqkind -> Bool;
# Uniqkind one-arm switches.
#
# These are if-then-else constructs;
# The first fn is called with the kind contents
# is it is of the appropriate flavor, otherwise
# the second ('otherwise') fn is called. Chaining
# these together allows a full 'case' to be simulated:
#
if_uniqkind_is_plaintype: (hut::Uniqkind, (Void -> X), (hut::Uniqkind -> X)) -> X;
if_uniqkind_is_boxedtype: (hut::Uniqkind, (Void -> X), (hut::Uniqkind -> X)) -> X;
if_uniqkind_is_kindseq: (hut::Uniqkind, (List( hut::Uniqkind ) -> X), (hut::Uniqkind -> X)) -> X;
if_uniqkind_is_kindfun: (hut::Uniqkind, ((List( hut::Uniqkind ), hut::Uniqkind) -> X), (hut::Uniqkind -> X)) -> X;
# Anormcode Calling_Convention Useless_Recordflag are used to
# classify different kinds of typelocked
# functions and records. As of now, they are
# roughly equivalent to:
#
# Calling_Convention
# = FIXED_CALLING_CONVENTION
# | VARIABLE_CALLING_CONVENTION { arg_is_raw: Bool,
# body_is_raw: Bool
# }
# ;
#
# Useless_Recordflag = USELESS_RECORDFLAG; # This appears to be something someone started and didn't finish. :-) -- Cynbe
#
# We treat both as abstract types so,
# so again we are unfortunately not
# able to use pattern matching with them.
#
# NOTE: VARIABLE_CALLING_CONVENTION flags are used by HIGHCODEs before we perform representation
# analysis while FIXED_CALLING_CONVENTION is used by HIGHCODEs after we perform representation
# analysis.
# Calling_Convention and Useless_Recordflag constructors:
#
make_variable_calling_convention: { arg_is_raw: Bool, body_is_raw: Bool } -> hut::Calling_Convention; # I don't yet get the raw/cooked type distinction.
fixed_calling_convention: hut::Calling_Convention; #
useless_recordflag: hut::Useless_Recordflag; # "rfc" == "record flag constructor"
# Calling_Convention and Useless_Recordflag deconstructors.
# The idea of these is to return the initial values used to create them:
#
unpack_variable_calling_convention: hut::Calling_Convention -> { arg_is_raw: Bool, body_is_raw: Bool }; # This is never used.
unpack_fixed_calling_convention: hut::Calling_Convention -> Void; # This is never used.
unpack_useless_recordflag: hut::Useless_Recordflag -> Void; # This is never used.
# Calling_Convention and Useless_Recordflag predicates:
#
calling_convention_is_variable: hut::Calling_Convention -> Bool; # "ffp" == "fn flag predicate"
calling_convention_is_fixed: hut::Calling_Convention -> Bool; #
useless_recordflag_is: hut::Useless_Recordflag -> Bool; # "rfp" == "record flag predicate"
# Calling_Convention and Useless_Recordflag one-arm switches.
# These are if-then-else constructs which can be chained to make a full 'case' statement:
#
if_calling_convention_is_variable: (hut::Calling_Convention, { arg_is_raw: Bool, body_is_raw: Bool } -> X, hut::Calling_Convention -> X) -> X;
if_calling_convention_is_fixed: (hut::Calling_Convention, Void -> X, hut::Calling_Convention -> X) -> X;
if_useless_recordflag_is: (hut::Useless_Recordflag, Void -> X, hut::Useless_Recordflag -> X) -> X; # Useless and unused both.
# Anormcode Uniqtyp is roughly equivalent to the following Mythryl datatype.
# Note that a TYPEFUN is a type -> type compiletime function,
# whereas an ARROW_TYPE represents a value -> value runtime function.
#
# Uniqtyp
# = TYPEVAR (Debruijn_Index, Int)
# | NAMED_TYPEVAR tmp::Codetemp
# | BASETYPE hut::Basetype
# | TYPEFUN (List( hut::Uniqkind ), hut::Uniqtyp)
# | APPLY_TYPEFUN (hut::Uniqtyp, List( hut::Uniqtyp ))
# | TYPESEQ List( hut::Uniqtyp )
# | TYPE_PROJECTION (hut::Uniqtyp, Int)
# | SUM_TYPE List( hut::Uniqtyp )
# | RECURSIVE_TYPE (hut::Uniqtyp, Int)
# | TUPLE_TYPE List( hut::Uniqtyp ) # record_flag hidden
# | ARROW_TYPE (hut::Calling_Convention, List(hut::Uniqtyp), List(hut::Uniqtyp))
# | BOXED_TYPE hut::Uniqtyp
# | ABSTRACT_TYPE hut::Uniqtyp
# | EXTENSIBLE_TOKEN_TYPE (Token, hut::Uniqtyp)
# | FATE_TYPE List(hut::Uniqtyp)
# | INDIRECT_TYPE_THUNK (hut::Uniqtyp, hut::Uniqtype)
# | TYPE_CLOSURE (Uniqtyp, Int, Int, Uniqtyp_Dictionary)
# ;
#
# We treat Uniqtyp as an abstract type
# to isolate clients from the complexity of the
# hashconsing machinery; this has the downside
# of preventing them from using pattern matching.
#
# Type applications (APPLY_TYPEFUN) and projections
# (TYPE_PROJECTION) are automatically reduced as needed:
# the client does not need to worry about whether
# a hut::Uniqtyp is in the normal form or not,
# all functions defined here automatically
# take care of this.
# Our Uniqtyp constructors:
#
make_debruijn_typevar_uniqtyp: (di::Debruijn_Index, Int) -> hut::Uniqtyp;
make_named_typevar_uniqtyp: tmp::Codetemp -> hut::Uniqtyp;
make_basetype_uniqtyp: hbt::Basetype -> hut::Uniqtyp;
make_typefun_uniqtyp: (List( hut::Uniqkind ), hut::Uniqtyp) -> hut::Uniqtyp;
make_apply_typefun_uniqtyp: (hut::Uniqtyp, List( hut::Uniqtyp )) -> hut::Uniqtyp;
make_typeseq_uniqtyp: List( hut::Uniqtyp ) -> hut::Uniqtyp;
make_ith_in_typeseq_uniqtyp: (hut::Uniqtyp, Int) -> hut::Uniqtyp;
make_sum_uniqtyp: List( hut::Uniqtyp ) -> hut::Uniqtyp;
make_recursive_uniqtyp: ((Int, hut::Uniqtyp, List(hut::Uniqtyp)), Int) -> hut::Uniqtyp;
make_extensible_token_uniqtyp: hut::Uniqtyp -> hut::Uniqtyp;
make_abstract_uniqtyp: hut::Uniqtyp -> hut::Uniqtyp;
make_boxed_uniqtyp: hut::Uniqtyp -> hut::Uniqtyp;
make_tuple_uniqtyp: List( hut::Uniqtyp ) -> hut::Uniqtyp;
make_arrow_uniqtyp: (hut::Calling_Convention, List(hut::Uniqtyp), List(hut::Uniqtyp)) -> hut::Uniqtyp;
# Our hut::Uniqtyp deconstructors.
# These are basically inverse to the above constructors:
#
unpack_debruijn_typevar_uniqtyp: hut::Uniqtyp -> (di::Debruijn_Index, Int);
unpack_named_typevar_uniqtyp: hut::Uniqtyp -> tmp::Codetemp;
unpack_basetype_uniqtyp: hut::Uniqtyp -> hbt::Basetype;
unpack_typefun_uniqtyp: hut::Uniqtyp -> (List( hut::Uniqkind ), hut::Uniqtyp);
unpack_apply_typefun_uniqtyp: hut::Uniqtyp -> (hut::Uniqtyp, List( hut::Uniqtyp ));
unpack_typeseq_uniqtyp: hut::Uniqtyp -> List( hut::Uniqtyp );
unpack_ith_in_typeseq_uniqtyp: hut::Uniqtyp -> (hut::Uniqtyp, Int);
unpack_sum_uniqtyp: hut::Uniqtyp -> List( hut::Uniqtyp );
unpack_recursive_uniqtyp: hut::Uniqtyp -> (((Int, hut::Uniqtyp, List( hut::Uniqtyp )) ), Int);
unpack_extensible_token_uniqtyp: hut::Uniqtyp -> hut::Uniqtyp;
unpack_abstract_uniqtyp: hut::Uniqtyp -> hut::Uniqtyp;
unpack_boxed_uniqtyp: hut::Uniqtyp -> hut::Uniqtyp;
unpack_tuple_uniqtyp: hut::Uniqtyp -> List( hut::Uniqtyp );
unpack_arrow_uniqtyp: hut::Uniqtyp -> (hut::Calling_Convention, List( hut::Uniqtyp ), List( hut::Uniqtyp ));
# Our hut::Uniqtyp predicates:
#
uniqtyp_is_debruijn_typevar: hut::Uniqtyp -> Bool;
uniqtyp_is_named_typevar: hut::Uniqtyp -> Bool;
uniqtyp_is_basetype: hut::Uniqtyp -> Bool;
uniqtyp_is_typefun: hut::Uniqtyp -> Bool;
uniqtyp_is_apply_typefun: hut::Uniqtyp -> Bool;
uniqtyp_is_typeseq: hut::Uniqtyp -> Bool;
uniqtyp_is_ith_in_typeseq: hut::Uniqtyp -> Bool;
uniqtyp_is_sum: hut::Uniqtyp -> Bool;
uniqtyp_is_recursive: hut::Uniqtyp -> Bool;
uniqtyp_is_extensible_token: hut::Uniqtyp -> Bool;
uniqtyp_is_abstract: hut::Uniqtyp -> Bool;
uniqtyp_is_boxed: hut::Uniqtyp -> Bool;
uniqtyp_is_tuple: hut::Uniqtyp -> Bool;
uniqtyp_is_arrow: hut::Uniqtyp -> Bool;
# Our hut::Uniqtyp one-armed switches.
# These are if-then-else constructs which may be
# daisy-chained to implement a complete 'case' statement:
#
if_uniqtyp_is_debruijn_typevar: (hut::Uniqtyp, ((di::Debruijn_Index, Int) -> X), (hut::Uniqtyp -> X)) -> X;
if_uniqtyp_is_named_typevar: (hut::Uniqtyp, (tmp::Codetemp -> X), (hut::Uniqtyp -> X)) -> X;
if_uniqtyp_is_basetype: (hut::Uniqtyp, (hbt::Basetype -> X), (hut::Uniqtyp -> X)) -> X;
if_uniqtyp_is_typefun: (hut::Uniqtyp, ((List( hut::Uniqkind ), hut::Uniqtyp) -> X), (hut::Uniqtyp -> X)) -> X;
if_uniqtyp_is_apply_typefun: (hut::Uniqtyp, ((hut::Uniqtyp, List( hut::Uniqtyp )) -> X), (hut::Uniqtyp -> X)) -> X;
if_uniqtyp_is_typeseq: (hut::Uniqtyp, (List( hut::Uniqtyp ) -> X), (hut::Uniqtyp -> X)) -> X;
if_uniqtyp_is_ith_in_typeseq: (hut::Uniqtyp, ((hut::Uniqtyp, Int) -> X), (hut::Uniqtyp -> X)) -> X;
if_uniqtyp_is_sum: (hut::Uniqtyp, (List( hut::Uniqtyp ) -> X), (hut::Uniqtyp -> X)) -> X;
if_uniqtyp_is_recursive: (hut::Uniqtyp, ((((Int, hut::Uniqtyp, List( hut::Uniqtyp ))), Int) -> X), (hut::Uniqtyp -> X)) -> X;
if_uniqtyp_is_extensible_token: (hut::Uniqtyp, (hut::Uniqtyp -> X), (hut::Uniqtyp -> X)) -> X;
if_uniqtyp_is_abstract: (hut::Uniqtyp, (hut::Uniqtyp -> X), (hut::Uniqtyp -> X)) -> X;
if_uniqtyp_is_boxed: (hut::Uniqtyp, (hut::Uniqtyp -> X), (hut::Uniqtyp -> X)) -> X;
if_uniqtyp_is_tuple: (hut::Uniqtyp, (List( hut::Uniqtyp ) -> X), (hut::Uniqtyp -> X)) -> X;
if_uniqtyp_is_arrow: (hut::Uniqtyp, ((hut::Calling_Convention, List( hut::Uniqtyp ), List( hut::Uniqtyp )) -> X), (hut::Uniqtyp -> X)) -> X;
# Anormcode hut::Uniqtype is roughly equivalent to the following Mythryl datatype
#
# hut::Uniqtype
# = TYPELOCKED_TYPE hut::Uniqtyp
# | PACKAGE_TYPE List( hut::Uniqtype )
# | GENERIC_PACKAGE_TYPE (List hut::Uniqtype, List hut::Uniqtype)
# | TYPEAGNOSTIC_TYPE (List hut::Uniqkind, List hut::Uniqtype)
# | INTERNAL_FATE_TYPE List( hut::Uniqtype )
# | INDIRECT_TYPE_THUNK (Uniqtype, Type)
# | TYPE_CLOSURE (Uniqtype, Int, Int, Uniqtyp_Dictionary)
# ;
#
# We treat Uniqtype as an abstract type
# to isolate clients from the complexity of the
# hashconsing machinery; this has the downside
# of preventing them from using pattern matching.
#
# Clients need not worry whether a hut::Uniqtype
# is in normal form.
# hut::Uniqtype constructors:
#
make_typ_uniqtype: hut::Uniqtyp -> hut::Uniqtype; # Heavily used!
make_package_uniqtype: List(hut::Uniqtype) -> hut::Uniqtype;
make_generic_package_uniqtype: (List(hut::Uniqtype), List(hut::Uniqtype)) -> hut::Uniqtype;
make_typeagnostic_uniqtype: (List(hut::Uniqkind), List(hut::Uniqtype)) -> hut::Uniqtype;
# hut::Uniqtype deconstructors.
# These are just inverses to the above four:
#
unpack_typ_uniqtype: hut::Uniqtype -> hut::Uniqtyp;
unpack_package_uniqtype: hut::Uniqtype -> List(hut::Uniqtype);
unpack_generic_package_uniqtype: hut::Uniqtype -> (List(hut::Uniqtype), List( hut::Uniqtype ));
unpack_typeagnostic_uniqtype: hut::Uniqtype -> (List(hut::Uniqkind), List( hut::Uniqtype ));
# hut::Uniqtype predicates:
#
uniqtype_is_typ: hut::Uniqtype -> Bool;
uniqtype_is_package: hut::Uniqtype -> Bool;
uniqtype_is_generic_package: hut::Uniqtype -> Bool;
uniqtype_is_typeagnostic: hut::Uniqtype -> Bool;
# hut::Uniqtype one-armed switches.
# These are if-then-else constructs which may be
# daisy-chained to implement a complete 'case' statement:
#
if_uniqtype_is_typ: (hut::Uniqtype, hut::Uniqtyp -> X, hut::Uniqtype -> X) -> X;
if_uniqtype_is_package: (hut::Uniqtype, List(hut::Uniqtype) -> X, hut::Uniqtype -> X) -> X;
if_uniqtype_is_generic_package: (hut::Uniqtype, (List(hut::Uniqtype), List(hut::Uniqtype)) -> X, hut::Uniqtype -> X) -> X;
if_uniqtype_is_typeagnostic: (hut::Uniqtype, (List(hut::Uniqkind), List(hut::Uniqtype)) -> X, hut::Uniqtype -> X) -> X;
# Because highcode hut::Uniqtyp is embedded
# inside highcode hut::Uniqtype, we supply the
# the following utility functions on building ltys that
# are based on simple typelocked typs. These are
# simple compositions of previously defined functions:
# hut::Uniqtyp-hut::Uniqtype constructors:
#
make_debruijn_typevar_uniqtype: (di::Debruijn_Index, Int) -> hut::Uniqtype;
make_basetype_uniqtype: hbt::Basetype -> hut::Uniqtype;
make_tuple_uniqtype: List(hut::Uniqtype) -> hut::Uniqtype;
make_arrow_uniqtype: (hut::Calling_Convention, List(hut::Uniqtype), List(hut::Uniqtype)) -> hut::Uniqtype;
# hut::Uniqtyp-hut::Uniqtype deconstructors.
# These are just inverses to the above four functions:
#
unpack_debruijn_typevar_uniqtype: hut::Uniqtype -> (di::Debruijn_Index, Int);
unpack_basetype_uniqtype: hut::Uniqtype -> hbt::Basetype;
unpack_tuple_uniqtype: hut::Uniqtype -> List(hut::Uniqtype);
unpack_arrow_uniqtype: hut::Uniqtype -> (hut::Calling_Convention, List(hut::Uniqtype), List(hut::Uniqtype));
# hut::Uniqtyp-hut::Uniqtype predicates:
#
uniqtype_is_debruijn_typevar: hut::Uniqtype -> Bool;
uniqtype_is_basetype: hut::Uniqtype -> Bool;
uniqtype_is_tuple_type: hut::Uniqtype -> Bool;
uniqtype_is_arrow_type: hut::Uniqtype -> Bool;
# hut::Uniqtyp-hut::Uniqtype one-arm switches.
# These are if-then-else constructs which may be
# daisy-chained to implement a complete 'case' statement:
#
if_uniqtype_is_debruijn_typevar: (hut::Uniqtype, (di::Debruijn_Index, Int) -> X, hut::Uniqtype -> X) -> X;
if_uniqtype_is_basetype: (hut::Uniqtype, hbt::Basetype -> X, hut::Uniqtype -> X) -> X;
if_uniqtype_is_tuple_type: (hut::Uniqtype, List(hut::Uniqtyp) -> X, hut::Uniqtype -> X) -> X;
if_uniqtype_is_arrow_type: (hut::Uniqtype, (hut::Calling_Convention, List(hut::Uniqtyp), List(hut::Uniqtyp)) -> X, hut::Uniqtype -> X) -> X;
################################################################################################
# The following functions are written for nextcode only.
# If you are writing code for highcode, you should not use any of these functions.
# The fate referred here is the internal fate introduced
# via FPS conversion; it is different from the source-level fate
# (Fate(X)) or control fate (Control_Fate(X)) where are represented
# as xt::primTypeCon_fate and xt::primTypeCon_control_fate respectively.
# fate-hut::Uniqtyp-hut::Uniqtype constructors:
#
make_uniqtyp_fate: List(hut::Uniqtyp) -> hut::Uniqtyp;
make_uniqtype_fate: List(hut::Uniqtype ) -> hut::Uniqtype;
# fate-hut::Uniqtyp-hut::Uniqtype deconstructors:
#
unpack_uniqtyp_fate: hut::Uniqtyp -> List(hut::Uniqtyp);
unpack_uniqtype_fate: hut::Uniqtype -> List(hut::Uniqtype );
# fate-hut::Uniqtyp-hut::Uniqtype predicates:
#
uniqtyp_is_fate: hut::Uniqtyp -> Bool;
uniqtype_is_fate: hut::Uniqtype -> Bool;
# fate-hut::Uniqtyp-hut::Uniqtype one-arm switches:
#
if_uniqtyp_is_fate: (hut::Uniqtyp, List( hut::Uniqtyp) -> X, hut::Uniqtyp -> X) -> X;
if_uniqtype_is_fate: (hut::Uniqtype, List( hut::Uniqtype ) -> X, hut::Uniqtype -> X) -> X;
################################################################################################
# The following functions are written for lambdacode_type only. If you
# are writing code for highcode only, don't use any of these functions.
# The idea is that in lambdacode, all (value or type) functions have single
# argument and single return-result. Ideally, we should define
# another set of datatypes for typs and ltys. But we want to avoid
# the translation from lambdacode_type to highcode types, so we let them
# share the same representations as much as possible.
#
# Ultimately, highcode_type should be separated into two files: one for
# highcode, another for lambdacode, but we will see if this is necessary.
# lambdacode hut::Uniqtyp-hut::Uniqtype constructors:
#
make_lambdacode_arrow_uniqtyp: (hut::Uniqtyp, hut::Uniqtyp ) -> hut::Uniqtyp;
make_lambdacode_arrow_uniqtype: (hut::Uniqtype, hut::Uniqtype) -> hut::Uniqtype;
make_lambdacode_typeagnostic_uniqtype: (List(hut::Uniqkind), hut::Uniqtype) -> hut::Uniqtype;
make_lambdacode_generic_package_uniqtype: (hut::Uniqtype, hut::Uniqtype) -> hut::Uniqtype;
# lambdacode hut::Uniqtyp-hut::Uniqtype deconstructors:
#
unpack_lambdacode_arrow_uniqtyp: hut::Uniqtyp -> (hut::Uniqtyp, hut::Uniqtyp);
unpack_lambdacode_arrow_uniqtype: hut::Uniqtype -> (hut::Uniqtype, hut::Uniqtype);
unpack_lambdacode_typeagnostic_uniqtype: hut::Uniqtype -> (List( hut::Uniqkind ), hut::Uniqtype);
unpack_lambdacode_generic_package_uniqtype: hut::Uniqtype -> (hut::Uniqtype, hut::Uniqtype);
# lambdacode hut::Uniqtyp-hut::Uniqtype predicates:
#
uniqtyp_is_lambdacode_arrow: hut::Uniqtyp -> Bool;
uniqtype_is_lambdacode_arrow: hut::Uniqtype -> Bool;
uniqtype_is_lambdacode_typeagnostic: hut::Uniqtype -> Bool;
uniqtype_is_lambdacode_generic_package: hut::Uniqtype -> Bool;
# lambdacode hut::Uniqtyp-hut::Uniqtype one-arm switches:
#
if_uniqtyp_is_lambdacode_arrow: (hut::Uniqtyp, (hut::Uniqtyp, hut::Uniqtyp ) -> X, hut::Uniqtyp -> X) -> X;
if_uniqtype_is_lambdacode_arrow: (hut::Uniqtype, (hut::Uniqtyp, hut::Uniqtyp ) -> X, hut::Uniqtype -> X) -> X;
if_uniqtype_is_lambdacode_typeagnostic: (hut::Uniqtype, (List(hut::Uniqkind), hut::Uniqtype) -> X, hut::Uniqtype -> X) -> X;
if_uniqtype_is_lambdacode_generic_package: (hut::Uniqtype, (hut::Uniqtype, hut::Uniqtype) -> X, hut::Uniqtype -> X) -> X;
};
end;
## Copyright (c) 1998 YALE FLINT PROJECT
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2013,
## released per terms of SMLNJ-COPYRIGHT.


