PreviousUpNext

15.4.476  src/lib/compiler/back/top/highcode/highcode-form.pkg

## highcode-form.pkg                            # "ltybasic.sml" in SML/NJ

# Compiled by:
#     src/lib/compiler/core.sublib


###                "There are only two kinds of math books:
###                 Those you cannot read beyond the first sentence,
###                 and those you cannot read beyond the first page."
###
###                         --  C.N. Yang, circa 1980 I think.
###                             [Nobel Prize in theoretical physics, 1957]


###             "I like mathematics because it is not human
###              and has nothing particular to do with this
###              planet or with the whole accidental universe
###              -- because like Spinoza's God, it won't love
###              us in return."
###
###                              -- Bertrand Russell, 1912


stipulate
    package acf =  anormcode_form;                              # anormcode_form                is from   src/lib/compiler/back/top/anormcode/anormcode-form.pkg
    package di  =  debruijn_index;                              # debruijn_index                is from   src/lib/compiler/front/typer/basics/debruijn-index.pkg
    package err =  error_message;                               # error_message                 is from   src/lib/compiler/front/basics/errormsg/error-message.pkg
    package hbo =  highcode_baseops;                            # highcode_baseops              is from   src/lib/compiler/back/top/highcode/highcode-baseops.pkg
    package hbt =  highcode_basetypes;                          # highcode_basetypes            is from   src/lib/compiler/back/top/highcode/highcode-basetypes.pkg
    package hct =  highcode_type;                               # highcode_type                 is from   src/lib/compiler/back/top/highcode/highcode-type.pkg
    package hut =  highcode_uniq_types;                         # highcode_uniq_types           is from   src/lib/compiler/back/top/highcode/highcode-uniq-types.pkg
    package lms =  list_mergesort;                              # list_mergesort                is from   src/lib/src/list-mergesort.pkg
    package pp  =  standard_prettyprinter;                      # standard_prettyprinter        is from   src/lib/prettyprint/big/src/standard-prettyprinter.pkg
    package tmp =  highcode_codetemp;                           # highcode_codetemp             is from   src/lib/compiler/back/top/highcode/highcode-codetemp.pkg
                        #
                        # Really should not refer to this.

    fun bug msg =   err::impossible ("highcode: " + msg);

    Pp = pp::Pp;

    say = global_controls::print::say;
herein

    package   highcode_form
    : (weak)  Highcode_Form                                     # Highcode_Form                 is from   src/lib/compiler/back/top/highcode/highcode-form.api
    {
        stipulate
            fun plist (p, [])     =>   "";                                                              # "plist" might be "print list".
                plist (p, x ! xs) =>   (p x) + (string::cat (map (\\ z =  (", " + (p z))) xs));
            end;
            #
            fun callnotes_to_string (hut::VARIABLE_CALLING_CONVENTION { arg_is_raw, body_is_raw })
                    => 
                    callnotes_to_string' (arg_is_raw, body_is_raw)
                    where
                        fun callnotes_to_string' (TRUE,  TRUE ) =>  "argRaw/bodyRaw";   # "r"=="raw", "c"=="cooked".
                            callnotes_to_string' (TRUE,  FALSE) =>  "argRaw/bodyCooked";
                            callnotes_to_string' (FALSE, TRUE ) =>  "argCooked/bodyRaw";
                            callnotes_to_string' (FALSE, FALSE) =>  "argCooked/bodyCooked";
                        end;
                    end;

                callnotes_to_string  hut::FIXED_CALLING_CONVENTION
                    =>
                    "f";
            end;
            #
            fun parw (p, (callnotes, t1, t2))                                                           # "parw" might be "polylambda arrow"...? or "print arrow"...?
                = 
                "<"
                + (p t1)
                + "> -"
                + callnotes_to_string callnotes
                + "-> <"
                + (p t2)
                + ">";
        herein

            include package   highcode_type;                                                    # highcode_type         is from   src/lib/compiler/back/top/highcode/highcode-type.pkg


            # Utility functions for constructing tkinds 
            #
            #
            fun n_plaintype_uniqkinds  n                                                # Also used in  translate_types  and  translate_deep_syntax_to_lambdacode
                = 
                h (n, [])
                where
                    fun h (n, results)
                        =
                        if (n < 1)   results;
                        else         h (n - 1,  plaintype_uniqkind ! results);
                        fi;
                end;


            stipulate
                # Precompute and save the three most
                # common cases -- 1, 2 or 3 args:
                #
                one___arg_fn =  make_kindfun_uniqkind  (n_plaintype_uniqkinds 1, plaintype_uniqkind);
                two___arg_fn =  make_kindfun_uniqkind  (n_plaintype_uniqkinds 2, plaintype_uniqkind);
                three_arg_fn =  make_kindfun_uniqkind  (n_plaintype_uniqkinds 3, plaintype_uniqkind);
            herein
                #
                fun make_n_arg_typefun_uniqkind 0 =>  plaintype_uniqkind;
                    make_n_arg_typefun_uniqkind 1 =>  one___arg_fn;
                    make_n_arg_typefun_uniqkind 2 =>  two___arg_fn;
                    make_n_arg_typefun_uniqkind 3 =>  three_arg_fn;
                    make_n_arg_typefun_uniqkind i =>  make_kindfun_uniqkind (n_plaintype_uniqkinds i, plaintype_uniqkind);
                end;
            end;

            # Base Calling_Conventions and Useless_Recordflags:
            #
            rawraw_variable_calling_convention
                =
                make_variable_calling_convention
                  {
                    arg_is_raw  => TRUE,
                    body_is_raw => TRUE
                  };

            # Called (only) from:   src/lib/compiler/back/top/improve/specialize-anormcode-to-least-general-type.pkg
            #
            fun update_calling_convention (x as hut::FIXED_CALLING_CONVENTION, { arg_is_raw => TRUE, body_is_raw => TRUE }) =>  x;
                update_calling_convention (x as hut::VARIABLE_CALLING_CONVENTION _, arg_is_raw__body_is_raw)                =>  make_variable_calling_convention  arg_is_raw__body_is_raw;
                #
                update_calling_convention _                                                                                 =>  bug "unexpected case in update_calling_convention";
            end;
            #
            fun unpack_calling_convention (hut::FIXED_CALLING_CONVENTION)                             =>  { arg_is_raw => TRUE, body_is_raw => TRUE };
                unpack_calling_convention (hut::VARIABLE_CALLING_CONVENTION arg_is_raw__body_is_raw ) =>   arg_is_raw__body_is_raw;
            end;
                # Unlike     hct::unpack_variable_calling_convention
                # and        hct::unpack_fixed_calling_convention
                # our             unpack_calling_convention
                # fn returns a usable result for any Calling_Convention arg.


            # Precompute various commonly used basetype uniqtypes:
            #
            int_uniqtype        =   make_basetype_uniqtype   hbt::basetype_tagged_int;
            int1_uniqtype       =   make_basetype_uniqtype   hbt::basetype_int1;
            float64_uniqtype    =   make_basetype_uniqtype   hbt::basetype_float64;
            string_uniqtype     =   make_basetype_uniqtype   hbt::basetype_string;
            exception_uniqtype  =   make_basetype_uniqtype   hbt::basetype_exception;
            truevoid_uniqtype   =   make_basetype_uniqtype   hbt::basetype_truevoid;
            #
            void_uniqtype       =   make_tuple_uniqtype [];
            #
            bool_uniqtype
                = 
                {   tbool = make_sum_uniqtype [void_uniqtype, void_uniqtype];
                    tsig_bool = make_typefun_uniqtype ([plaintype_uniqkind], tbool);
                    make_recursive_uniqtype((1, tsig_bool, []), 0);
                };
            #
            list_uniqtype         # Not exported -- used for printing.
                  =
                  {   alpha = make_debruijn_typevar_uniqtype (di::innermost, 0);
                      tlist = make_debruijn_typevar_uniqtype (di::innersnd, 0);
                      alist = make_apply_typefun_uniqtype (tlist, [alpha]);
                      tcc_cons = make_tuple_uniqtype [alpha, alist];
                      tlist = make_typefun_uniqtype([plaintype_uniqkind], make_sum_uniqtype [tcc_cons, void_uniqtype]);
                                            # The order here should be consistent with that in
                                            #     src/lib/compiler/front/typer/types/more-type-types.pkg
                      tsig_list = make_typefun_uniqtype([make_n_arg_typefun_uniqkind 1], tlist);
                      make_recursive_uniqtype((1, tsig_list, []), 0);
                  };
            #
            fun make_typevar_i_uniqtype     i   =  make_debruijn_typevar_uniqtype (di::innermost, i);
            #
            fun make_ref_uniqtype          x    =  make_apply_typefun_uniqtype (make_basetype_uniqtype hbt::basetype_ref,               [x]);
            fun make_rw_vector_uniqtype     x   =  make_apply_typefun_uniqtype (make_basetype_uniqtype hbt::basetype_rw_vector,         [x]);
            fun make_ro_vector_uniqtype     x   =  make_apply_typefun_uniqtype (make_basetype_uniqtype hbt::basetype_vector,            [x]);
            fun make_exception_tag_uniqtype x   =  make_apply_typefun_uniqtype (make_basetype_uniqtype hbt::basetype_exception_tag,     [x]);

            # Prebuilt basetype uniqtypoids:
            #
            int_uniqtypoid       =   make_type_uniqtypoid         int_uniqtype;
            int1_uniqtypoid      =   make_type_uniqtypoid       int1_uniqtype;
            float64_uniqtypoid   =   make_type_uniqtypoid     float64_uniqtype;
            string_uniqtypoid    =   make_type_uniqtypoid      string_uniqtype;
            exception_uniqtypoid =   make_type_uniqtypoid   exception_uniqtype;
            truevoid_uniqtypoid  =   make_type_uniqtypoid    truevoid_uniqtype;
            void_uniqtypoid      =   make_type_uniqtypoid        void_uniqtype;
            bool_uniqtypoid      =   make_type_uniqtypoid        bool_uniqtype;

            # Uniqtypoid constructors:
            #
            make_typevar_i_uniqtypoid           = make_type_uniqtypoid o make_typevar_i_uniqtype;
            make_ref_uniqtypoid                 = make_type_uniqtypoid o make_ref_uniqtype o unpack_type_uniqtypoid;
            make_rw_vector_uniqtypoid           = make_type_uniqtypoid o make_rw_vector_uniqtype o unpack_type_uniqtypoid;
            make_ro_vector_uniqtypoid           = make_type_uniqtypoid o make_ro_vector_uniqtype o unpack_type_uniqtypoid;
            make_exception_tag_uniqtypoid       = make_type_uniqtypoid o make_exception_tag_uniqtype o unpack_type_uniqtypoid;


            ############################################################################
            #            UTILITY FUNCTIONS FOR TESTING EQUIVALENCE
            ############################################################################


            # Testing equivalence of tkinds,
            # types, ltys, fflags, and rflags:
            #
            my same_uniqkind:           (hut::Uniqkind, hut::Uniqkind) -> Bool       =  hut::same_uniqkind;
            my same_uniqtype:               (hut::Uniqtype, hut::Uniqtype) -> Bool   =  hut::same_uniqtype;
            my same_uniqtypoid:         (hut::Uniqtypoid, hut::Uniqtypoid) -> Bool       =  hut::same_uniqtypoid;
            my same_callnotes:       (hut::Calling_Convention, hut::Calling_Convention) -> Bool         =  hut::same_callnotes;
            my same_recordflag:         (hut::Useless_Recordflag, hut::Useless_Recordflag) -> Bool =  hut::same_recordflag;

            # Testing the equivalence for types and
            # ltys with relaxed constraints:
            #
            my similar_uniqtypes:   (hut::Uniqtype, hut::Uniqtype) -> Bool               =  hut::similar_uniqtypes;
            my similar_uniqtypoids:        (hut::Uniqtypoid, hut::Uniqtypoid) -> Bool =  hut::similar_uniqtypoids;

            ############################################################################
            #            UTILITY FUNCTIONS FOR PRETTY PRINTING
            ############################################################################

            # Prettyprinting of tkinds, types, and ltys:
            #
            fun uniqkind_to_string (x:  hut::Uniqkind)
                = 
                g (hut::uniqkind_to_kind x)
                where
                    fun g  hut::kind::PLAINTYPE =>  "K0";
                        g  hut::kind::BOXEDTYPE =>  "KB0";

                        g (hut::kind::KINDFUN (ks, k))
                            =>  
                            "<" + (plist (uniqkind_to_string, ks)) + "->" + (uniqkind_to_string k) + ">";

                        g (hut::kind::KINDSEQ zs)
                            =>
                            "KS(" + (plist (uniqkind_to_string, zs)) + ")";
                    end;
                end;
            #
            fun uniqtype_to_string (x:  hut::Uniqtype)
                =
                g (hut::uniqtype_to_type x)
                where
                    fun g (hut::type::DEBRUIJN_TYPEVAR (i, j))  =>  "DEBRUIJN_TYPEVAR(" + (di::di_print i) + ", " + (int::to_string j) + ")";
                        g (hut::type::NAMED_TYPEVAR v) =>  "NAMED_TYPEVAR (v" + (int::to_string v) + ")";

                        g (hut::type::BASETYPE pt)
                            =>
                            hbt::basetype_to_string pt;

                        g (hut::type::TYPEFUN (ks, t))
                            => 
                            "(\\[" + plist (uniqkind_to_string, ks) + "]." + (uniqtype_to_string t) + ")";

                        g (hut::type::APPLY_TYPEFUN (t, [])) => uniqtype_to_string t + "[]";
                        g (hut::type::APPLY_TYPEFUN (t, zs)) => (uniqtype_to_string t) + "[" + (plist (uniqtype_to_string, zs)) + "]";

                        g (hut::type::TYPESEQ zs)      =>  "TYPESEQ(" + (plist (uniqtype_to_string, zs)) + ")";
                        g (hut::type::ITH_IN_TYPESEQ (t, i)) =>  "ITH_IN_TYPESEQ(" + (uniqtype_to_string t) + ", " + (int::to_string i) + ")";
                        g (hut::type::SUM tcs)     =>  "SUM(" + (plist (uniqtype_to_string, tcs)) + ")";

                        g (hut::type::RECURSIVE ((_, tc, ts), i))
                            => 
                            if   (same_uniqtype (x, bool_uniqtype))  "BOOL"; 
                            elif (same_uniqtype (x, list_uniqtype))  "LIST"; 
                            else

                              #  ntc = case ts
                              #            [] => tc;
                              #            _  => make_apply_typefun_uniqtype (tc, ts);
                              #        esac;

                                 "DATA { " + "DATA" +
                                                              #  "["              +
                                                              #  (uniqtype_to_string tc)    +
                                                              #  "] &&"           +
                                                              #  (plist (uniqtype_to_string, ts)) +
                                                              #  "&&"
                                 "===="           +
                                 (int::to_string i)         +
                                 "}";

                             fi;

                        g (hut::type::ABSTRACT t)   =>  "ABSTRACT(" + (uniqtype_to_string t) + ")";
                        g (hut::type::BOXED t)      =>  "BOXED(" + (uniqtype_to_string t) + ")";
                        g (hut::type::TUPLE(_, zs)) =>  "TUPLE<" + (plist (uniqtype_to_string, zs)) + ">";

                        g (hut::type::ARROW (ff, z1, z2)) =>  parw (\\ u = plist (uniqtype_to_string, u), (ff, z1, z2));
                        g (hut::type::PARROW _)           =>  bug "unexpected TC_PARROW in uniqtype_to_string";

                        g (hut::type::EXTENSIBLE_TOKEN (k, t))
                            => 
                            if (hut::token_is_valid k)    (hut::token_abbreviation k) + "(" + (uniqtype_to_string t) + ")";
                            else                         bug "unexpected TC_EXTENSIBLE_TOKEN type in uniqtype_to_string";
                            fi;

                        g (hut::type::FATE ts)
                            =>
                            "Count(" + (plist (uniqtype_to_string, ts)) + ")";

                        g (hut::type::INDIRECT_TYPE_THUNK _) =>  bug "unexpected TC_INDIRECT in uniqtype_to_string";
                        g (hut::type::TYPE_CLOSURE  _) =>  bug "unexpected TC_CLOSURE in uniqtype_to_string";
                    end;
                end;                    # fun uniqtype_to_string 
            #
            fun uniqtypoid_to_string (x:  hut::Uniqtypoid)
                =
                g (hut::uniqtypoid_to_typoid x)
                where
                    fun h (i, t)
                        =
                        "(" + (int::to_string i) + ", " + (uniqtypoid_to_string t) + ")";
                    #
                    fun g (hut::typoid::TYPE t) => uniqtype_to_string t;
                        g (hut::typoid::PACKAGE zs) => "PACKAGE { " + (plist (uniqtypoid_to_string, zs)) + "}";

                        g (hut::typoid::GENERIC_PACKAGE (ts1, ts2))
                           => 
                           "(" + (plist (uniqtypoid_to_string, ts1)) + ") ==> ("
                           + (plist (uniqtypoid_to_string, ts2)) + ")";

                        g (hut::typoid::TYPEAGNOSTIC (ks, ts))
                           => 
                           "(TYPEAGNOSTIC[" + plist (uniqkind_to_string, ks) + "]."
                           + (plist (uniqtypoid_to_string, ts)) + ")";

                        g (hut::typoid::FATE ts)
                            =>
                            "FATE(" + (plist (uniqtypoid_to_string, ts)) + ")";

                        g (hut::typoid::INDIRECT_TYPE_THUNK _) => bug "unexpected INDIRECT_TYPE_THUNK in uniqtypoid_to_string";
                        g (hut::typoid::TYPE_CLOSURE      _) => bug "unexpected TYPE_CLOSURE in uniqtypoid_to_string";
                    end;

                end;                    # fun uniqtypoid_to_string 



            fun prettyprint_uniqkind  (pp:Pp)   (x:  hut::Uniqkind)
                = 
                g (hut::uniqkind_to_kind x)
                where
                    fun g  hut::kind::PLAINTYPE =>  pp.lit "hut::kind::PLAINTYPE";
                        g  hut::kind::BOXEDTYPE =>  pp.lit "hut::kind::BOXEDTYPE";

                        g (hut::kind::KINDFUN (ks, k))
                            =>  
                            pp.box' 0 0 {.
                                pp.lit "hut::kind::KINDFUN (";
                                pp.ind 4;
                                pp.txt " ";

                                pp::seqx {. pp.txt ", "; }  (prettyprint_uniqkind pp)  ks;

                                pp.ind 0;
                                pp.cut ();
                                pp.lit "->";
                                pp.ind 4;
                                pp.txt " ";

                                prettyprint_uniqkind pp k;

                                pp.ind 0;
                                pp.cut ();
                                pp.lit ")";
                            };

                        g (hut::kind::KINDSEQ zs)
                            =>
                            pp.box' 0 0 {.
                                pp.lit "hut::kind::KINDSEQ (";
                                pp.ind 4;
                                pp.txt " ";

                                pp::seqx {. pp.txt ", "; }  (prettyprint_uniqkind pp)  zs;

                                pp.ind 0;
                                pp.cut ();
                                pp.lit ")";
                            };
                    end;
                end;
            #
            fun prettyprint_uniqtype  (pp:Pp)  (x:  hut::Uniqtype)
                =
                g (hut::uniqtype_to_type x)
                where
                    fun g (hut::type::DEBRUIJN_TYPEVAR (i, j))
                            =>
                            pp.lit ("hut::type::DEBRUIJN_TYPEVAR(" + (di::di_print i) + ", " + (int::to_string j) + ")");

                        g (hut::type::NAMED_TYPEVAR v)
                            =>
                            pp.lit ("hut::type::NAMED_TYPEVAR (v" + (int::to_string v) + ")");

                        g (hut::type::BASETYPE pt)
                            =>
                            pp.lit ("hut::type::BASETYPE " + (hbt::basetype_to_string pt));

                        g (hut::type::TYPEFUN (ks, t))
                            => 
                            pp.box' 0 0 {.
                                pp.lit "hut::type::TYPEFUN (";
                                pp.ind 4;
                                pp.txt " ";

                                pp.box' 0 2 {.
                                    pp.lit "kinds => [";
                                    pp.ind 4;
                                    pp.txt " ";

                                    pp::seqx {. pp.txt ", "; }  (prettyprint_uniqkind pp)  ks;

                                    pp.ind 0;
                                    pp.txt " ";
                                    pp.lit "]";
                                };
                                pp.endlit ",";
                                pp.txt " ";

                                pp.box' 0 2 {.
                                    pp.lit "type =>";
                                    pp.ind 4;
                                    pp.txt " ";

                                    prettyprint_uniqtype pp t;

                                    pp.ind 0;
                                    pp.txt " ";
                                    pp.lit "]";
                                };
                                pp.ind 0;
                                pp.cut ();
                                pp.lit ")";
                            };

                        g (hut::type::APPLY_TYPEFUN (t, []))
                            =>
                            pp.box' 0 0 {.
                                pp.lit "hut::type::APPLY_TYPEFUN (";
                                pp.ind 4;
                                pp.txt " ";
                                pp.lit "t =>";
                                pp.txt " ";
                                prettyprint_uniqtype pp t;
                                pp.txt " ";
                                pp.lit "[]";
                                pp.txt " ";
                                pp.ind 0;
                                pp.cut ();
                                pp.lit ")";
                            };

                        g (hut::type::APPLY_TYPEFUN (t, zs))
                            =>
                            pp.box' 0 0 {.
                                pp.lit "hut::type::APPLY_TYPEFUN (";
                                pp.ind 4;
                                pp.txt " ";

                                pp.box' 0 -1 {.
                                    pp.lit "t =>";
                                    pp.ind 4;
                                    pp.txt " ";
                                    prettyprint_uniqtype pp t;
                                };

                                pp.endlit ",";
                                pp.txt " ";

                                pp.box' 0 2 {.
                                    pp.lit "zs => [";
                                    pp.ind 4;
                                    pp.txt " ";

                                    pp::seqx  {. pp.txt ", "; }  (prettyprint_uniqtype pp)  zs;

                                    pp.ind 0;
                                    pp.txt " ";
                                    pp.lit "]";
                                };
                                pp.txt " ";
                                pp.ind 0;
                                pp.cut ();
                                pp.lit ")";
                            };

                        g (hut::type::TYPESEQ zs)
                            =>
                            pp.box' 0 0 {.
                                pp.lit "hut::type::TYPESEQ(";
                                pp.ind 4;
                                pp.txt " ";

                                pp::seqx {. pp.txt ", "; }  (prettyprint_uniqtype pp)  zs;

                                pp.txt " ";
                                pp.ind 0;
                                pp.cut ();
                                pp.lit ")";
                            };

                        g (hut::type::ITH_IN_TYPESEQ (t, i))
                            =>
                            pp.box' 0 0 {.
                                pp.lit "hut::type::ITH_IN_TYPESEQ(";
                                pp.ind 4;
                                pp.txt " ";

                                prettyprint_uniqtype pp t;

                                pp.endlit ",";
                                pp.txt " ";

                                pp.lit (int::to_string i);

                                pp.ind 0;
                                pp.cut ();
                                pp.lit ")";
                            };

                        g (hut::type::SUM tcs)
                            =>
                            pp.box' 0 0 {.      
                                pp.lit "hut::type::SUM(";
                                pp.ind 4;
                                pp.txt " ";

                                pp::seqx  {. pp.txt ", "; }   (prettyprint_uniqtype pp)  tcs;

                                pp.ind 0;
                                pp.cut ();
                                pp.lit ")";
                            };

                        g (hut::type::RECURSIVE ((_, tc, ts), i))
                            => 
                            if   (same_uniqtype (x, bool_uniqtype))  pp.lit "BOOL"; 
                            elif (same_uniqtype (x, list_uniqtype))  pp.lit "LIST"; 
                            else

                              #  ntc = case ts
                              #            [] => tc;
                              #            _  => make_apply_typefun_uniqtype (tc, ts);
                              #        esac;

                                pp.box' 0 0 {.
                                    pp.lit "DATA {";
                                    pp.ind 4;
                                    pp.txt " ";
                                    pp.lit "DATA";

                                    pp.box' 0 0 {.      
                                        pp.lit "[";
                                        pp.ind 4;
                                        pp.txt " ";
                                        prettyprint_uniqtype pp tc;
                                        pp.txt " ";
                                        pp.ind 0;
                                        pp.txt " ";
                                        pp.lit "]";
                                    };
                                    pp.ind 0;
                                    pp.cut ();
                                    pp.lit "&&";

                                    pp.ind 4;
                                    pp.txt " ";

                                    pp::seqx {. pp.txt ", "; }   (prettyprint_uniqtype pp)  ts;

                                    pp.ind 0;
                                    pp.cut ();
                                    pp.lit "&&";

                                    pp.ind 4;
                                    pp.txt " ";

                                    pp.lit "====";
                                    pp.lit (int::to_string i);

                                    pp.ind 0;
                                    pp.txt " ";
                                    pp.lit "}";
                                };
                            fi;

                        g (hut::type::ABSTRACT t)
                            =>
                            pp.box' 0 0 {.
                                pp.lit "hut::type::ABSTRACT(";
                                pp.ind 4;
                                pp.txt " ";
                                prettyprint_uniqtype pp  t;
                                pp.ind 0;
                                pp.cut ();
                                pp.lit ")";
                            };

                        g (hut::type::BOXED t)
                            =>
                            pp.box' 0 0 {.
                                pp.lit "hut::type::BOXED(";
                                pp.ind 4;
                                pp.txt " ";
                                prettyprint_uniqtype pp  t;
                                pp.ind 0;
                                pp.cut ();
                                pp.lit ")";
                            };

                        g (hut::type::TUPLE(_, zs))
                            =>
                            pp.box' 0 0 {.
                                pp.lit "hut::type::TUPLE(";
                                pp.ind 4;
                                pp.txt " ";

                                pp::seqx {. pp.txt ", "; }  (prettyprint_uniqtype pp)  zs;

                                pp.ind 0;
                                pp.cut ();
                                pp.lit ")";
                            };

                        g (hut::type::ARROW (ff, z1, z2))
                            =>
                            pp.box' 0 0 {.
                                pp.lit "hut::type::ARROW(";
                                pp.ind 4;
                                pp.txt " ";

                                pp::seqx {. pp.txt ", "; }  (prettyprint_uniqtype pp)  z1;

                                pp.txt " ";
                                pp.lit (callnotes_to_string ff);
                                pp.txt " ";

                                pp::seqx {. pp.txt ", "; }  (prettyprint_uniqtype pp)  z2;

                                pp.ind 0;
                                pp.cut ();
                                pp.lit ")";
                            };

                        g (hut::type::PARROW _)           =>  bug "unexpected TC_PARROW in uniqtype_to_string";

                        g (hut::type::EXTENSIBLE_TOKEN (k, t))
                            => 
                            if (hut::token_is_valid k)
                                pp.box' 0 0 {.
                                    pp.lit "hut::type::EXTENSIBLE_TOKEN(";
                                    pp.ind 4;
                                    pp.txt " ";

                                    pp.lit (hut::token_abbreviation k);

                                    pp.box' 0 2 {.
                                        pp.lit "(";
                                        pp.ind 4;
                                        pp.txt " ";

                                        prettyprint_uniqtype pp t;

                                        pp.ind 0;
                                        pp.cut ();
                                        pp.lit ")";
                                    };
                                    pp.ind 0;
                                    pp.cut ();
                                    pp.lit ")";
                                };
                            else
                                bug "unexpected TC_EXTENSIBLE_TOKEN type in uniqtype_to_string";
                            fi;

                        g (hut::type::FATE ts)
                            =>
                            pp.box' 0 0 {.
                                pp.lit "hut::type::FATE(";
                                pp.ind 4;
                                pp.txt " ";

                                pp::seqx {. pp.txt ", "; }  (prettyprint_uniqtype pp) ts;

                                pp.ind 0;
                                pp.cut ();
                                pp.lit ")";
                            };

                        g (hut::type::INDIRECT_TYPE_THUNK _) =>  bug "unexpected TC_INDIRECT in uniqtype_to_string";
                        g (hut::type::TYPE_CLOSURE  _) =>  bug "unexpected TC_CLOSURE in uniqtype_to_string";
                    end;
                end;                    # fun prettyprint_uniqtype

            fun prettyprint_uniqtypoid  (pp:Pp)   (x:  hut::Uniqtypoid)
                =
                g (hut::uniqtypoid_to_typoid x)
                where
                    fun h (i, t)
                        =
                        pp.box' 0 0 {.
                            pp.lit "(";
                            pp.ind 4;
                            pp.lit (int::to_string i);
                            pp.endlit ",";
                            pp.txt " ";
                            prettyprint_uniqtypoid pp t;
                            pp.ind 0;
                            pp.cut ();
                            pp.lit ")";
                        };
                    #
                    fun g (hut::typoid::TYPE t)
                            =>
                            {
                                prettyprint_uniqtype pp t;
                            };

                        g (hut::typoid::PACKAGE zs)
                            =>
                            pp.box' 0 0 {.
                                pp.lit "PACKAGE {";
                                pp.ind 4;
                                pp.txt " ";

                                pp::seqx {. pp.txt ", "; }  (prettyprint_uniqtypoid pp)  zs;

                                pp.ind 0;
                                pp.txt " ";
                                pp.lit "}";
                            };

                        g (hut::typoid::GENERIC_PACKAGE (ts1, ts2))
                            =>
                            pp.box' 0 0 {.
                                pp.lit "GENERIC_PACKAGE (";
                                pp.ind 4;
                                pp.txt " ";

                                pp::seqx {. pp.txt ", "; }  (prettyprint_uniqtypoid pp) ts1;

                                pp.ind 0;
                                pp.cut ();
                                pp.lit ") ==> (";
                                pp.ind 4;
                                pp.txt " ";

                                pp::seqx {. pp.txt ", "; }  (prettyprint_uniqtypoid pp) ts2;

                                pp.ind 0;
                                pp.cut ();
                                pp.lit ")";
                            };

                        g (hut::typoid::TYPEAGNOSTIC (ks, ts))
                            => 
                            pp.box' 0 0 {.
                                pp.lit "TYPEAGNOSTIC(";
                                pp.ind 2;
                                pp.txt " ";
                                pp.box' 1 0 {.
                                    pp.lit "kinds =>";
                                    pp.txt " ";
                                    pp.box' 1 2 {.
                                        pp.lit "[";
                                        pp.ind 2;
                                        pp.txt " ";

                                        pp::seqx {. pp.txt ", "; }  (prettyprint_uniqkind pp) ks;

                                        pp.ind 0;
                                        pp.txt " ";
                                        pp.lit "]";
                                    };
                                };
                                pp.endlit ",";
                                pp.txt " ";

                                pp.box' 1 0 {.
                                    pp.lit "typoids =>";
                                    pp.txt " ";
                                    pp.box' 1 2 {.
                                        pp.lit "[";
                                        pp.ind 2;
                                        pp.txt " ";

                                        pp::seqx {. pp.txt ", "; }  (prettyprint_uniqtypoid pp)  ts;

                                        pp.ind 0;
                                        pp.txt " ";
                                        pp.lit "]";
                                    };
                                };

                                pp.ind 0;
                                pp.cut ();
                                pp.lit ")";
                            };

                        g (hut::typoid::FATE ts)
                            =>
                            pp.box' 0 0 {.
                                pp.lit "FATE(";
                                pp.ind 4;

                                pp::seqx {. pp.txt ", "; }  (prettyprint_uniqtypoid pp)  ts;

                                pp.ind 0;
                                pp.cut ();
                                pp.lit ")";
                            };

                        g (hut::typoid::INDIRECT_TYPE_THUNK _) => bug "unexpected INDIRECT_TYPE_THUNK in prettyprint_uniqtypoid";
                        g (hut::typoid::TYPE_CLOSURE        _) => bug "unexpected TYPE_CLOSURE in prettyprint_uniqtypoid";
                    end;

                end;                    # fun prettyprint_uniqtypoid


            # Finding out the depth for a type's
            # innermost-bound free variables 
            #
            my max_freevar_depth_in_uniqtype:   (      hut::Uniqtype,   di::Debruijn_Depth) -> di::Debruijn_Depth   =   hut::max_freevar_depth_in_uniqtype;
            my max_freevar_depth_in_uniqtypes:  (List( hut::Uniqtype ), di::Debruijn_Depth) -> di::Debruijn_Depth   =   hut::max_freevar_depth_in_uniqtypes;

            # Adjusting an hut::Uniqtypoid or hut::Uniqtype
            # from one depth to another 
            #
            fun change_depth_of_uniqtypoid (lt, d, nd)
                = 
                if (d == nd)   lt; 
                else           hut::make_type_closure_uniqtypoid (lt, 0, nd - d, hut::empty_uniqtype_dictionary);
                fi;
            #
            fun change_depth_of_uniqtype (tc, d, nd)
                = 
                if (d == nd)   tc; 
                else           hut::make_type_closure_uniqtype (tc, 0, nd - d, hut::empty_uniqtype_dictionary);
                fi;

            stipulate
                fun make_type_dictionary (i, k, dd, e)
                    = 
                    if (i >= k)   e;
                    else          make_type_dictionary (i+1, k, dd, hut::cons_entry_onto_uniqtype_dictionary (e, (NULL, dd+i)));
                    fi;
            herein 
                #
                fun change_k_depth_of_uniqtypoid (lt, d, nd, k)
                    = 
                    if (d == nd)  lt; 
                    else          hut::make_type_closure_uniqtypoid (lt, k, nd-d+k, make_type_dictionary (0, k, nd-d, hut::empty_uniqtype_dictionary));
                    fi;
                #
                fun change_k_depth_of_uniqtype (tc, d, nd, k)
                    = 
                    if (d == nd)  tc; 
                    else          hut::make_type_closure_uniqtype (tc, k, nd-d+k, make_type_dictionary (0, k, nd-d, hut::empty_uniqtype_dictionary));
                    fi;

            end;


            ############################################################################
            #            UTILITY FUNCTIONS ON LTY DICTIONARY
            ############################################################################

            # Utility values and functions on lty_env 
            #
            Highcode_Variable_To_Uniqtypoid_Map
                =
                int_red_black_map::Map( (hut::Uniqtypoid, di::Debruijn_Depth) ); 

            exception HIGHCODE_VARIABLE_NOT_FOUND;

            empty_highcode_variable_to_uniqtypoid_map
                =
                int_red_black_map::empty
                :
                Highcode_Variable_To_Uniqtypoid_Map;

            #
            fun get_uniqtypoid_for_var (venv, lv, nd)
                = 
                case (int_red_black_map::get (venv, lv))
                    #
                    THE (lt, d)
                        => 
                        if   (d == nd)   lt;
                        elif (d >  nd)   bug "unexpected depth info in ltLookup";
                        else             hut::make_type_closure_uniqtypoid (lt, 0, nd - d, hut::empty_uniqtype_dictionary);
                        fi;

                    NULL => {   say "**** hmmm, I didn't find the variable ";
                                say (int::to_string lv); say "\n";
                                raise exception HIGHCODE_VARIABLE_NOT_FOUND;
                            };
                esac;
            #
            fun set_uniqtypoid_for_var (venv, lv, lt, d)
                =
                int_red_black_map::set (venv, lv, (lt, d));

        end;                                                                                                                    # top-level stipulate

        # Instantiate a typeagnostic type
        # or a higher-order constructor.
        #
        # Compare with    apply_typeagnostic_type_to_arglist_with_checking_thunk()   below,
        # which does the same thing with more checking.
        #
        fun apply_typeagnostic_type_to_arglist
              (
                lt:  hut::Uniqtypoid,                                                   # typefun
                ts:  List( hut::Uniqtype )                                              # arglist for typefun.
              )
            = 
            {   nt = hut::reduce_uniqtypoid_to_weak_head_normal_form  lt;
            
                case (/* lt_outX */ hut::uniqtypoid_to_typoid nt, ts)
        
                    (hut::typoid::TYPEAGNOSTIC (ks, b),  ts)
                        => 
                        {   nenv  = hut::cons_entry_onto_uniqtype_dictionary (hut::empty_uniqtype_dictionary, (THE ts, 0));
                            #
                            map (\\ x = hut::make_type_closure_uniqtypoid (x, 1, 0, nenv))
                                b;
                        };

                    (_, []) =>  [nt];   #  This requires further clarifications !!! XXX FIXME BUGGO 
                     _      =>  bug "incorrect hut::Uniqtypoid instantiation in apply_typeagnsotic_type_to_arglist";
                esac;
           }; 
        #
        fun apply_typeagnostic_type_to_arglist_with_single_result
              (
                lt:  hut::Uniqtypoid,
                ts:  List( hut::Uniqtype )
              )
            = 
            case (apply_typeagnostic_type_to_arglist (lt, ts))
                #
                [y] => y;
                _   => bug "unexpected pmacroExpandTypeagnosticLambdaTypeOrHOC";
            esac;


        ############################################################################
        #                      KIND-CHECKING ROUTINES
        ############################################################################

        exception KIND_TYPE_CHECK_FAILED;
        exception APPLY_TYPEFUN_CHECK_FAILED;

        # tk_subkind returns TRUE if k1 is a subkind of k2, or if they are 
        # equivalent kinds.  It is NOT commutative.  tks_subkind is the same
        # thing, component-wise on lists of kinds.
        #
        fun are_subkinds (ks1, ks2)
            =
            paired_lists::all is_subkind (ks1, ks2)   #  Component-wise 

        also
        fun is_subkind (k1, k2)
            = 
            same_uniqkind (k1, k2)               #  reflexive 
            or
            case (hut::uniqkind_to_kind k1, hut::uniqkind_to_kind k2)   
                #
                ( hut::kind::BOXEDTYPE,
                  hut::kind::PLAINTYPE
                )
                    =>
                    TRUE; #  ground kinds (base case) 

                # This next case is WRONG, but necessary until the
                # infrastructure is there to give proper boxed kinds to
                # certain types (e.g., REF:  Omega -> Omega_b)                  XXX BUGGO FIXME
                #
                ( hut::kind::PLAINTYPE,
                  hut::kind::BOXEDTYPE
                )
                    =>
                    TRUE;

                ( hut::kind::KINDSEQ  ks1,
                  hut::kind::KINDSEQ  ks2
                )
                    =>     
                    are_subkinds (ks1, ks2);

                ( hut::kind::KINDFUN (ks1, k1'),
                  hut::kind::KINDFUN (ks2, k2')
                )
                    => 
                    are_subkinds (ks1, ks2)   and           #  Contravariant 
                    is_subkind  (k1', k2');

                _ => FALSE;
            esac;

        # Is kind 'k' typelocked?
        #
        fun tk_is_mono k
            =
            is_subkind (k, plaintype_uniqkind);

        # Assert that k1 is a subkind of k2:
        #
        fun assert_this_is_a_subkind_of_that { this, that }
            =
            if (not (is_subkind (this, that)))   raise exception KIND_TYPE_CHECK_FAILED;   fi;

        # Assert that a kind is typelocked:
        #
        fun tk_assert_is_mono k
            =
            if (not (tk_is_mono k))   raise exception KIND_TYPE_CHECK_FAILED;   fi;

        # Select the ith element
        # from a kind sequence:
        #
        fun select_ith_in_type_sequence (tk, i)
            = 
            case (hut::uniqkind_to_kind tk)
                #
                (hut::kind::KINDSEQ  ks)
                    =>
                    list::nth (ks, i)
                    except
                        _ = raise exception KIND_TYPE_CHECK_FAILED;

                _ => raise exception KIND_TYPE_CHECK_FAILED;
            esac;

        #
        fun tks_eqv (ks1, ks2)
            =
            same_uniqkind (make_kindseq_uniqkind ks1, make_kindseq_uniqkind ks2);
        #
        fun tk_app (tk, tks)
            = 
            case (hut::uniqkind_to_kind tk)
                #
                hut::kind::KINDFUN (a, b)
                    =>
                    if (tks_eqv (a, tks))   b;
                    else                    raise exception KIND_TYPE_CHECK_FAILED;
                    fi;

                _ => raise exception KIND_TYPE_CHECK_FAILED;
            esac;

        # Check the application of types of kinds `tks'
        # to a type function of kind `tk':
        #
        fun tk_app (tk, tks)
            = 
            case (hut::uniqkind_to_kind tk)
                #
                hut::kind::KINDFUN (a, b)
                    =>
                    if (are_subkinds (tks, a))   b;
                    else                         raise exception KIND_TYPE_CHECK_FAILED;
                    fi;

                _   => raise exception KIND_TYPE_CHECK_FAILED;
            esac;



        # Kind-checking naturally requires traversing type graphs.
        #
        # To avoid re-traversing bits of the dag, we use a dictionary
        # to memoize the kind of each hut::Uniqtype we process.
        #
        # One problem is that a hut::Uniqtype can have different kinds,
        # depending on the valuations of its free variables.
        #
        # So this dictionary maps a hut::Uniqtype to an association list
        # that maps the kinds of the free variables in the hut::Uniqtype
        # (represented as a TYPEKIND_TYPESEQ) to the hut::Uniqtype's kind.
        #
        package uniqtype_dictionary                                             # XXX BUGGO FIXME is there any reason to be using binary_map_g instead of the standard red_black_map_g ?
            =
            binary_map_g (                                                      # binary_map_g                  is from   src/lib/src/binary-map-g.pkg
                Key = hut::Uniqtype;
                compare = hut::compare_uniqtypes;
            );

        package memo:
            api {
                Dictionary; 
                #
                make_dictionary:        Void -> Dictionary;
                #
                recall_or_compute_uniqkind_of_uniqtype
                  :
                  ( Dictionary,
                    hut::Debruijn_To_Uniqkind_Listlist,
                    hut::Uniqtype,
                    (Void -> hut::Uniqkind)
                  )
                  ->
                  hut::Uniqkind;
            }
        {
            package uniqtype_dictionary
                =
                red_black_map_g (                                               # red_black_map_g               is from   src/lib/src/red-black-map-g.pkg
                    #
                    Key     = hut::Uniqtype;
                    compare = hut::compare_uniqtypes;
                );

            Dictionary
                =
                Ref( uniqtype_dictionary::Map( List ( (hut::Uniqkind, hut::Uniqkind) ) ) );             # XXX BUGGO FIXME More icky thread-hostile global mutable state.

            my make_dictionary:  Void -> Dictionary
                =
                REF  o  (\\ () = uniqtype_dictionary::empty);


            #
            fun recall_or_compute_uniqkind_of_uniqtype
                  (
                    dictionary:                         Dictionary,
                    debruijn_to_uniqkind_listlist:      hut::Debruijn_To_Uniqkind_Listlist,             # Maps typevars to their Uniqkinds.
                    uniqtype:                           hut::Uniqtype,                                  # Our primary input.
                    uniqkind_of_uniqtype_thunk:         Void -> hut::Uniqkind                           # This will compute needed result from first principles, if we don't find it in our cache.
                  ):                                    hut::Uniqkind
                =
                case (hut::get_uniqkinds_of_free_typevars_of_uniqtype (debruijn_to_uniqkind_listlist, uniqtype))
                    #
                    THE (uniqkinds_of_free_typevars:  List(hut::Uniqkind))
                        =>
                        {
                            # Encode those as a hut::kind::KINDSEQ:
                            #   
                            typevars_kindseq =  make_kindseq_uniqkind  uniqkinds_of_free_typevars;

                            # Query the dictionary:
                            #
                            kci =   case (uniqtype_dictionary::get (*dictionary, uniqtype))
                                        #
                                        THE kci =>  kci;
                                        NULL    =>  [];
                                    esac;

                            # Get for an equivalent dictionary:
                            #
                            fun same_dictionary_identifier (typevars_kindseq', _)
                                =
                                same_uniqkind (typevars_kindseq, typevars_kindseq');

                            case (list::find  same_dictionary_identifier  kci)
                                #
                                THE (_, uniqkind)       # Cache hit -- return cached kind.
                                    =>
                                    uniqkind;

                                NULL =>                 # Not in the list -- compute and cache type's kind.
                                    uniqkind
                                    where

                                        #
                                        uniqkind =  uniqkind_of_uniqtype_thunk ();
                                        #
                                        kci' = (typevars_kindseq, uniqkind) ! kci;

                                        dictionary :=  uniqtype_dictionary::set (*dictionary, uniqtype, kci');
                                    end;
                            esac;
                        };

                   NULL =>
                      # freevars were not available.
                      # We'll have to recompute and
                      # cannot cache the result.
                      # 
                      uniqkind_of_uniqtype_thunk ();
               esac;

        };      # package memo 


        # Return the kind of a given type
        # in the given kind dictionary 
        #
        fun get_uniqkind_of_uniqtype_thunk ()                   # Evaluating the thunk allocates a fresh memo dictionary.
            =
            get_uniqkind_of_uniqtype
            where

                dictionary =  memo::make_dictionary ();
                #
                fun get_uniqkind_of_uniqtype  debruijn_to_uniqkind_listlist  (uniqtype: hut::Uniqtype)
                    =
                    memo::recall_or_compute_uniqkind_of_uniqtype (dictionary, debruijn_to_uniqkind_listlist, uniqtype, uniqkind_of_uniqtype_thunk)
                    where

                        g =  get_uniqkind_of_uniqtype  debruijn_to_uniqkind_listlist;           # Default recursive invocation.

                        # How to compute the kind of a type
                        #
                        fun uniqkind_of_uniqtype_thunk ()
                            =
                            case (hut::uniqtype_to_type  uniqtype)
                                #
                                hut::type::DEBRUIJN_TYPEVAR (depth, index) =>   hut::debruijn_to_uniqkind (debruijn_to_uniqkind_listlist, depth, index);
                                hut::type::NAMED_TYPEVAR _                =>   bug "TC_NAMED_VAR not supported yet in get_uniqkind_of_uniqtype";

                                hut::type::BASETYPE pt                    =>   make_n_arg_typefun_uniqkind (highcode_basetypes::basetype_arity pt);
                                hut::type::TYPEFUN (ks, tc)               =>   make_kindfun_uniqkind (ks, get_uniqkind_of_uniqtype (hut::prepend_uniqkind_list_to_map (debruijn_to_uniqkind_listlist, ks)) tc);

                                hut::type::APPLY_TYPEFUN (tc, tcs)        =>   tk_app (g tc, map g tcs);
                                hut::type::TYPESEQ tcs                    =>   make_kindseq_uniqkind (map g tcs);
                                hut::type::ITH_IN_TYPESEQ (tc, i)         =>   select_ith_in_type_sequence (g tc, i);

                                hut::type::SUM tcs
                                    =>
                                    {   list::apply (tk_assert_is_mono o g) tcs;
                                        plaintype_uniqkind;
                                    };

                                hut::type::RECURSIVE ((n, tc, ts), i)
                                    =>
                                    {   k = g tc;

                                        nk = case ts   
                                                 [] =>  k; 
                                                 _  =>  tk_app (k, map g ts);
                                             esac;
                                 
                                        case (hut::uniqkind_to_kind nk)   
                                            #
                                             hut::kind::KINDFUN (a, b)
                                                 => 
                                                 {   arg =  case a    [x] => x;
                                                                       _  => make_kindseq_uniqkind a;
                                                            esac;
                                         
                                                     if (is_subkind (arg, b))           #  order? 
                                                         #
                                                         n == 1   ??   b
                                                                  ::   select_ith_in_type_sequence (arg, i);
                                                     else
                                                         raise exception KIND_TYPE_CHECK_FAILED;
                                                     fi;
                                                 };

                                             _ => raise exception KIND_TYPE_CHECK_FAILED;
                                        esac;
                                    };

                                hut::type::ABSTRACT tc
                                    =>
                                    {   tk_assert_is_mono (g tc);
                                        plaintype_uniqkind;
                                    };

                                hut::type::BOXED tc
                                    =>
                                    {   tk_assert_is_mono (g tc);
                                        plaintype_uniqkind;
                                    };

                                hut::type::TUPLE (_, tcs)
                                    =>
                                    {   list::apply (tk_assert_is_mono o g) tcs;
                                        plaintype_uniqkind;
                                    };

                                hut::type::ARROW (_, ts1, ts2)
                                    =>
                                    {   list::apply (tk_assert_is_mono o g) ts1;
                                        list::apply (tk_assert_is_mono o g) ts2;
                                        plaintype_uniqkind;
                                    };

                                hut::type::EXTENSIBLE_TOKEN(_, tc)
                                    =>
                                    {   tk_assert_is_mono (g tc);
                                        plaintype_uniqkind;
                                    };

                                hut::type::PARROW       _ => bug "unexpected TC_PARROW in tkTypeConstructor";
                                hut::type::TYPE_CLOSURE      _ => bug "unexpected TC_CLOSURE in tkTypeConstructor";
                                hut::type::INDIRECT_TYPE_THUNK     _ => bug "unexpected TC_INDIRECT in tkTypeConstructor";
                                hut::type::FATE _ => bug "unexpected TC_FATE in tkTypeConstructor";
                            esac;
                    end;                                        # fun get_uniqkind_of_uniqtype 
            end;                                                # fun get_uniqkind_of_uniqtype_thunk


        # Assert that the kind of `type'
        # is a subkind of `kind' in `debruijn_to_uniqkind_listlist':
        #
        fun assert_type_has_subkind_of_kind_thunk ()                                    # Evaluating the thunk allocates a new memo dictionary.
            =
            assert_type_has_subkind_of_kind
            where
                get_uniqkind_of_uniqtype =   get_uniqkind_of_uniqtype_thunk ();                 # Allocate a fresh memo dictionary.
                #
                fun assert_type_has_subkind_of_kind   debruijn_to_uniqkind_listlist   (kind, type)
                    =
                    assert_this_is_a_subkind_of_that
                      {
                        this =>  get_uniqkind_of_uniqtype  debruijn_to_uniqkind_listlist  type,
                        that =>  kind
                      };
            end;

        #  hut::Uniqtypoid application with kind-checking (exported) 
        #
        # Compare with   apply_typeagnostic_type_to_arglist
        # above, which does the same thing with less checking.
        #
        fun apply_typeagnostic_type_to_arglist_with_checking_thunk ()                                                   # Evaluating the thunk allocates a new memo dictionary.
            =
            apply_typeagnostic_type_to_arglist_with_checking
            where

                assert_type_has_subkind_of_kind =
                assert_type_has_subkind_of_kind_thunk ();                                                               # Evaluating the thunk allocates a new memo dictionary.
                #
                fun apply_typeagnostic_type_to_arglist_with_checking
                      (
                        fn_type:                        hut::Uniqtypoid,                                                        # Fn type.
                        fn_arg_types:                   List(hut::Uniqtype),                                            # Types of args to which fn is being applied.
                        debruijn_to_uniqkind_listlist:  hut::Debruijn_To_Uniqkind_Listlist
                      )
                    = 
                    {   fn_type_in_whnf =  hut::reduce_uniqtypoid_to_weak_head_normal_form  fn_type;

                        case (/* lt_outX */ hut::uniqtypoid_to_typoid fn_type_in_whnf, fn_arg_types)
                            #
                            (hut::typoid::TYPEAGNOSTIC (fn_parameter_kinds, b), fn_arg_types)                           # 'b' == 'body type(s)'...?  It has type   List(Uniqtypoid)
                                => 
                                {   paired_lists::apply (assert_type_has_subkind_of_kind  debruijn_to_uniqkind_listlist) (fn_parameter_kinds, fn_arg_types);
                                    #
                                    fun h x
                                        =
                                        hut::make_type_closure_uniqtypoid (x, 1, 0, hut::cons_entry_onto_uniqtype_dictionary (hut::empty_uniqtype_dictionary, (THE fn_arg_types, 0)));

                                    map h b;
                                };

                            (_, []) => [fn_type_in_whnf];                                                               #  ? problematic  XXX BUGGO FIXME   Appears to say "don't complain about bad fn type if no args".
                            _       => raise exception APPLY_TYPEFUN_CHECK_FAILED;                                      # This is the only place we raise this exception.
                        esac;
                    };
            
            end;


        # A special hut::Uniqtypoid application used inside
        #
        #     src/lib/compiler/back/top/improve/specialize-anormcode-to-least-general-type.pkg
        #
        fun lt_sp_adj (ks, lt, ts, dist, bnl)
            = 
            h (dist, 1, bnl, btenv)
            where
                btenv =  hut::cons_entry_onto_uniqtype_dictionary  (hut::empty_uniqtype_dictionary, (THE ts, 0));
                #
                fun h (abslevel, ol, nl, tenv)
                    =
                    if (abslevel == 0)
                        #
                        hut::make_type_closure_uniqtypoid (lt, ol, nl, tenv);
                        #
                    elif (abslevel > 0)
                        #
                        h (abslevel - 1, ol+1, nl+1, hut::cons_entry_onto_uniqtype_dictionary (tenv, (NULL, nl)));
                    else
                         bug "unexpected cases in ltAdjSt";
                    fi;
            end;

        # A special type application used
        # inside src/lib/compiler/back/top/improve/specialize-anormcode-to-least-general-type.pkg
        #
        fun tc_sp_adj (ks, tc, ts, dist, bnl)
            =
            h (dist, 1, bnl, btenv)
            where
                btenv =  hut::cons_entry_onto_uniqtype_dictionary (hut::empty_uniqtype_dictionary, (THE ts, 0));
                #
                fun h (abslevel, ol, nl, tenv)
                    =
                    if   (abslevel == 0)   hut::make_type_closure_uniqtype (tc, ol, nl, tenv);
                    elif (abslevel >  0)   h (abslevel - 1, ol+1, nl+1, hut::cons_entry_onto_uniqtype_dictionary (tenv, (NULL, nl)));
                    else                   bug "unexpected cases in tcAdjSt";
                    fi;

            end;

        # * Sinking the hut::Uniqtypoid one-level down -- used inside specialize-anormcode-to-least-general-type.pkg 
        #
        fun lt_sp_sink (ks, lt, d, nd)
            = 
            {   fun h (abslevel, ol, nl, tenv)
                    =
                    if (abslevel == 0)
                        #
                        hut::make_type_closure_uniqtypoid (lt, ol, nl, tenv);
                        #
                    elif (abslevel > 0)
                        #
                        h (abslevel - 1, ol+1, nl+1, hut::cons_entry_onto_uniqtype_dictionary(tenv, (NULL, nl)));
                    else
                        bug "unexpected cases in ltSinkSt";
                    fi;

                nt = h (nd-d, 0, 1, hut::empty_uniqtype_dictionary);
            
                nt; #  was reduceLambdaTypeToNormalForm nt 
            };

        # * Sinking the type one-level down -- used inside specialize-anormcode-to-least-general-type.pkg 
        #
        fun tc_sp_sink (ks, tc, d, nd)
            = 
            {   fun h (abslevel, ol, nl, tenv)
                    =
                    if   (abslevel == 0)    hut::make_type_closure_uniqtype (tc, ol, nl, tenv);
                    elif (abslevel >  0)    h (abslevel - 1, ol+1, nl+1, hut::cons_entry_onto_uniqtype_dictionary (tenv, (NULL, nl)));
                    else                    bug "unexpected cases in ltSinkSt";
                    fi;

                nt = h (nd-d, 0, 1, hut::empty_uniqtype_dictionary);
            
                nt; #  was reduceTypeConstructorToNormalForm nt 
            };

        # Utility functions used in nextcode:
        #
        fun lt_is_fate lt
            = 
            case (hut::uniqtypoid_to_typoid lt)
                #
                hut::typoid::FATE _
                    =>
                    TRUE;

                hut::typoid::TYPE tc
                    => 
                    case (hut::uniqtype_to_type tc)    hut::type::FATE _ =>  TRUE;
                                                     _                =>  FALSE;
                    esac;

                 _  => FALSE;
            esac;
        #
        fun ltw_is_fate (lt, f, g, h)
            = 
            case (hut::uniqtypoid_to_typoid lt)
                #
                hut::typoid::FATE t
                    =>
                    f t;

                hut::typoid::TYPE tc
                    => 
                    case (hut::uniqtype_to_type tc)    hut::type::FATE x =>  g x;
                                                     _                =>  h lt;
                    esac;

                _ => h lt;
            esac;

        #
        fun tc_bug tc s =  bug (s + "\n\n" + (uniqtype_to_string tc) + "\n\n");
        fun lt_bug lt s =  bug (s + "\n\n" + (uniqtypoid_to_string   lt) + "\n\n");

        # Other misc utility functions:
        #
        fun tc_get_field (tc, i)
            = 
            case (hut::uniqtype_to_type tc)
                #
                hut::type::TUPLE (_, zs)
                    =>
                 (list::nth (zs, i))
                 except
                     _ = bug "wrong TC_TUPLE in tc_get_field";

                _ => tc_bug tc "wrong TCs in tc_get_field";
            esac;
        #
        fun lt_get_field (t, i)
            = 
            case (hut::uniqtypoid_to_typoid t)
                #
                hut::typoid::PACKAGE ts
                    => 
                    (list::nth (ts, i))
                    except
                        _ = bug "incorrect PACKAGE in lt_get_field";
                #
                hut::typoid::TYPE tc
                    =>
                    make_type_uniqtypoid (tc_get_field (tc, i));

                _ => bug "incorrect lambda types in lt_get_field";
            esac;
        #
        fun tc_swap t
            = 
            case (hut::uniqtype_to_type t)
                #
                hut::type::ARROW (hut::VARIABLE_CALLING_CONVENTION { arg_is_raw => r1, body_is_raw => r2 }, [s1], [s2])
                    =>        make_arrow_uniqtype (hut::VARIABLE_CALLING_CONVENTION { arg_is_raw => r2, body_is_raw => r1 }, [s2], [s1]);
                #
                hut::type::ARROW (hut::FIXED_CALLING_CONVENTION, [s1], [s2])
                    =>        make_arrow_uniqtype (hut::FIXED_CALLING_CONVENTION, [s2], [s1]);

                _ => bug "unexpected types in tc_swap";
            esac;
        #
        fun lt_swap t
            = 
            case (hut::uniqtypoid_to_typoid t)
                #
                (hut::typoid::TYPEAGNOSTIC (ks, [x]))
                    =>
                    make_typeagnostic_uniqtypoid (ks, [lt_swap x]);

                (hut::typoid::TYPE x)
                    =>
                    make_type_uniqtypoid (tc_swap x);

                _ => bug "unexpected type in lt_swap";
            esac;

        # Functions that manipulate the highcode
        # function and record types
        #
        fun ltc_fkfun ( { call_as=>acf::CALL_AS_GENERIC_PACKAGE,       ... }: acf::Function_Notes, atys, rtys) 
                =>
                make_generic_package_uniqtypoid  (       atys, rtys);

            ltc_fkfun ( { call_as=>acf::CALL_AS_FUNCTION fixed, ... },           atys, rtys)
                =>
                make_arrow_uniqtypoid (fixed, atys, rtys);
        end;
        #
        fun ltd_fkfun lambda_type
            = 
            if (uniqtypoid_is_generic_package lambda_type)
                unpack_generic_package_uniqtypoid lambda_type;
            else
                my (_, atys, rtys) = unpack_arrow_uniqtypoid lambda_type;
                (atys, rtys);
            fi;
        #
        fun ltc_rkind (acf::RK_TUPLE _, lts) =>  make_tuple_uniqtypoid lts;
            ltc_rkind (acf::RK_PACKAGE,  lts) =>  make_package_uniqtypoid   lts;
            ltc_rkind (acf::RK_VECTOR t, _)  =>  make_ro_vector_uniqtypoid (make_type_uniqtypoid t);
        end;
        #
        fun ltd_rkind (lt, i)
            =
            lt_get_field (lt, i);

        #############################################################################
        #             UTILITY FUNCTIONS USED BY POST-REPRESENTATION ANALYSIS
        #############################################################################

        # Figure the appropriate baseop given a type:
        #
        fun tc_upd_prim tc
            = 
            h (hut::uniqtype_to_type tc)
            where
                fun h (hut::type::BASETYPE pt)
                        => 
                        if   (hbt::ubxupd pt)     hbo::SET_VECSLOT_TO_TAGGED_INT_VALUE; # Tagged_Int case.
                        elif (hbt::bxupd  pt)     hbo::SET_VECSLOT_TO_BOXED_VALUE;      # Everything else.
                        else                      hbo::RW_VECTOR_SET;                   # Int1, Float64, List, Null_Or, Generic_Machine_Word, Single_Word, Tagged_Int, Untagged_Int, Boxed, Dynamically_Typed.
                        fi;

                    h (hut::type::TUPLE _ | hut::type::ARROW _)
                        =>
                        hbo::SET_VECSLOT_TO_BOXED_VALUE;

                    h (hut::type::RECURSIVE ((1, tc, ts), 0))
                        => 
                        {   ntc = case ts    [] => tc;
                                              _ => make_apply_typefun_uniqtype (tc, ts);
                                  esac;

                            case (hut::uniqtype_to_type ntc)
                                #
                                hut::type::TYPEFUN([k], b) =>  h (hut::uniqtype_to_type b);
                                _                         =>  hbo::RW_VECTOR_SET;
                            esac;
                      };

                    h (hut::type::SUM tcs)
                        => 
                        {   fun g (a ! r) =>   same_uniqtype (a, void_uniqtype)
                                                   ??  g r
                                                   ::  FALSE;
                                g []      => TRUE;
                            end;

                            if (g tcs)  hbo::SET_VECSLOT_TO_TAGGED_INT_VALUE;
                            else        hbo::RW_VECTOR_SET;
                            fi;
                      };

                    h _ => hbo::RW_VECTOR_SET;
                end;
            
            end;

        fun uniqkind_to_uniqtypoid (uniqkind: hut::Uniqkind)   :   hut::Uniqtypoid  
            = 
            case (hut::uniqkind_to_kind  uniqkind)
                #             
                hut::kind::PLAINTYPE            =>  int_uniqtypoid;
                hut::kind::BOXEDTYPE            =>  int_uniqtypoid;
                hut::kind::KINDSEQ ks           =>  make_tuple_uniqtypoid (map uniqkind_to_uniqtypoid ks);
                hut::kind::KINDFUN (ks, k)      =>  make_arrow_uniqtypoid (fixed_calling_convention, [make_tuple_uniqtypoid (map uniqkind_to_uniqtypoid ks)], [uniqkind_to_uniqtypoid k]);
            esac;


        # tnarrow_fn:  Void -> ((hut::Uniqtype -> hut::Uniqtype) * (hut::Uniqtypoid -> hut::Uniqtypoid) * (Void->Void))
        #
        fun tnarrow_fn ()
            = 
            ( tc_map  o  hut::reduce_uniqtype_to_normal_form,
              lt_map  o  hut::reduce_uniqtypoid_to_normal_form,
              \\ () = ()
            )
            where
                fun tc_narrow tcf  t
                    = 
                    case (hut::uniqtype_to_type  t)
                        #
                        hut::type::BASETYPE pt
                            => 
                            if (hbt::isvoid pt)  truevoid_uniqtype;
                            else                t;
                            fi;

                        hut::type::TUPLE (_, tcs)
                            =>
                            make_tuple_uniqtype (map tcf tcs);

                        hut::type::ARROW (r, ts1, ts2)
                            => 
                            make_arrow_uniqtype (fixed_calling_convention,  map tcf ts1,  map tcf ts2);

                        _ => truevoid_uniqtype;
                    esac;
                #
                fun lt_narrow (tcf, ltf) t
                    = 
                    case (hut::uniqtypoid_to_typoid t)
                        #
                        hut::typoid::TYPE tc                    =>  make_type_uniqtypoid (tcf tc);
                        hut::typoid::PACKAGE ts                 =>  make_package_uniqtypoid (map ltf ts);
                        #
                        hut::typoid::GENERIC_PACKAGE (ts1, ts2) =>  make_generic_package_uniqtypoid (map ltf ts1, map ltf ts2);
                        hut::typoid::TYPEAGNOSTIC (ks, xs)      =>  make_generic_package_uniqtypoid([make_package_uniqtypoid (map uniqkind_to_uniqtypoid ks)], map ltf xs);

                        hut::typoid::FATE _                     =>  bug "unexpected hut::typoid::FATE in ltNarrow";
                        hut::typoid::INDIRECT_TYPE_THUNK _      =>  bug "unexpected hut::typoid::INDIRECT_TYPE_THUNK in ltNarrow";
                        hut::typoid::TYPE_CLOSURE _             =>  bug "unexpected hut::typoid::TYPE_CLOSURE in ltNarrow";
                    esac;

                my { tc_map, lt_map }
                    =
                    highcode_dictionary::tmemo_fn
                      {
                        tcf => tc_narrow,
                        ltf => lt_narrow
                      };

            end;                # fun tnarrow_fn 

        # twrap_fn:    Bool -> ( hut::Uniqtype -> hut::Uniqtype,
        #                        hut::Uniqtypoid -> hut::Uniqtypoid,
        #                        hut::Uniqtype -> hut::Uniqtype,
        #                        hut::Uniqtypoid -> hut::Uniqtypoid,
        #                        Void -> Void
        #                      ) 
        #
        fun twrap_fn bbb
            = 
            {   fun tc_wmap (w, u) t
                    =
                    case (hut::uniqtype_to_type t)
                        #
                        (hut::type::DEBRUIJN_TYPEVAR _ | hut::type::NAMED_TYPEVAR _) => t;
                        hut::type::BASETYPE bt => if (hbt::basetype_is_unboxed bt) make_extensible_token_uniqtype t; else t;fi;
                        hut::type::TYPEFUN (ks, tc) => make_typefun_uniqtype (ks, w tc); #  impossible case 
                        hut::type::APPLY_TYPEFUN (tc, tcs) => make_apply_typefun_uniqtype (w tc, map w tcs);
                        hut::type::TYPESEQ tcs => make_typeseq_uniqtype (map w tcs);
                        hut::type::ITH_IN_TYPESEQ (tc, i) => make_ith_in_typeseq_uniqtype (w tc, i);
                        hut::type::SUM tcs => make_sum_uniqtype (map w tcs);
                        #
                        hut::type::RECURSIVE ((n, tc, ts), i)
                            => 
                            make_recursive_uniqtype((n, hut::reduce_uniqtype_to_normal_form (u tc), map w ts), i); 
                        #
                        hut::type::TUPLE (_, ts) => make_extensible_token_uniqtype (make_tuple_uniqtype (map w ts)); #  ? 
                        hut::type::ARROW (hut::VARIABLE_CALLING_CONVENTION { arg_is_raw => b1, body_is_raw => b2 }, ts1, ts2)
                            =>  
                            {   nts1 = case ts1    # Too specific !
                                           [t11, t12] => [w t11, w t12]; 
                                           _          => [w (hut::uniqtype_list_to_uniqtype_tuple ts1)];
                                       esac;

                                nts2 = [w (hut::uniqtype_list_to_uniqtype_tuple ts2)];

                                nt = make_arrow_uniqtype (fixed_calling_convention, nts1, nts2);

                                if b1           nt;
                                else   make_extensible_token_uniqtype nt;
                                fi;
                            };
                        #
                        hut::type::ARROW (hut::FIXED_CALLING_CONVENTION, _, _)
                            =>  
                            bug "unexpected TC_FIXED_ARROW in tc_umap";

                        hut::type::EXTENSIBLE_TOKEN (k, t) =>  bug "unexpected token hut::Uniqtype in tc_wmap";
                        hut::type::BOXED _                 =>  bug "unexpected TC_BOXED in tc_wmap";
                        hut::type::ABSTRACT _              =>  bug "unexpected TC_ABSTRACT in tc_wmap";
                        _                               =>  bug "unexpected other types in tc_wmap";
                    esac;
                #
                fun tc_umap (u, w) t
                    =
                    case (hut::uniqtype_to_type t)
                        #
                        (hut::type::DEBRUIJN_TYPEVAR _ | hut::type::NAMED_TYPEVAR _ | hut::type::BASETYPE _) => t;
                        hut::type::TYPEFUN (ks, tc) => make_typefun_uniqtype (ks, u tc); /* impossible case */ 
                        hut::type::APPLY_TYPEFUN (tc, tcs) => make_apply_typefun_uniqtype (u tc, map w tcs);
                        hut::type::TYPESEQ tcs => make_typeseq_uniqtype (map u tcs);
                        hut::type::ITH_IN_TYPESEQ (tc, i) => make_ith_in_typeseq_uniqtype (u tc, i);
                        hut::type::SUM tcs => make_sum_uniqtype (map u tcs);
                        #
                        hut::type::RECURSIVE ((n, tc, ts), i)
                            => 
                            make_recursive_uniqtype((n, hut::reduce_uniqtype_to_normal_form (u tc), map w ts), i); 
                        #
                        hut::type::TUPLE (rk, tcs) => make_tuple_uniqtype (map u tcs);
                        #
                        hut::type::ARROW (hut::VARIABLE_CALLING_CONVENTION { arg_is_raw => b1, body_is_raw => b2 }, ts1, ts2)
                            =>  
                            make_arrow_uniqtype (fixed_calling_convention, map u ts1, map u ts2);
                        #
                        hut::type::ARROW (hut::FIXED_CALLING_CONVENTION, _, _)
                            =>  
                            bug "unexpected TC_FIXED_ARROW in tc_umap";
                        #
                        hut::type::PARROW   _ => bug "unexpected TC_PARROW in tc_umap";
                        hut::type::BOXED    _ => bug "unexpected TC_BOXED in tc_umap";
                        hut::type::ABSTRACT _ => bug "unexpected TC_ABSTRACT in tc_umap";
                        #
                        hut::type::EXTENSIBLE_TOKEN (k, t)
                            => 
                            if (hut::same_token (k, hut::wrap_token)) 
                                bug "unexpected TC_WRAP in tc_umap";
                            else
                                hut::type_to_uniqtype (hut::type::EXTENSIBLE_TOKEN (k, u t));
                            fi;

                        _ => bug "unexpected other types in tc_umap";
                    esac;
                #
                fun lt_umap (tcf, ltf) t
                    = 
                    case (hut::uniqtypoid_to_typoid t)
                        #
                        hut::typoid::TYPE tc                    => make_type_uniqtypoid (tcf tc);
                        hut::typoid::PACKAGE ts                 => make_package_uniqtypoid (map ltf ts);
                        hut::typoid::GENERIC_PACKAGE (ts1, ts2)   => make_generic_package_uniqtypoid (map ltf ts1, map ltf ts2);
                        hut::typoid::TYPEAGNOSTIC (ks, xs)      => make_typeagnostic_uniqtypoid (ks, map ltf xs);
                        hut::typoid::FATE   _                   => bug "unexpected CNTs in lt_umap";
                        hut::typoid::INDIRECT_TYPE_THUNK _      => bug "unexpected INDs in lt_umap";
                        hut::typoid::TYPE_CLOSURE       _       => bug "unexpected ENVs in lt_umap";
                    esac;

                (highcode_dictionary::wmemo_fn { tc_wmap, tc_umap, lt_umap })
                    ->
                    { tc_wmap=>tc_wrap, tc_umap=>tc_map, lt_umap=>lt_map, cleanup };
        
        #
                fun lt_wrap x
                    = 
                    if_uniqtypoid_is_type ( x,
                                           (\\ tc =  make_type_uniqtypoid (tc_wrap tc)),
                                           \\ _  =  bug "unexpected case in ltWrap"
                                         );

            
                ( tc_wrap o hut::reduce_uniqtype_to_normal_form,
                  lt_wrap o hut::reduce_uniqtypoid_to_normal_form, 
                  tc_map  o hut::reduce_uniqtype_to_normal_form,
                  lt_map  o hut::reduce_uniqtypoid_to_normal_form,
                  cleanup
                );
            };


        #########################################################################
        #            SUBSTITION OF NAMED VARS IN A TYC/LTY
        #########################################################################

        package uniqtypoid_dictionary
            =
            binary_map_g (
                #
                Key     =  hut::Uniqtypoid;
                compare =  hut::compare_uniqtypoids;
            );

        # Used (only) in                src/lib/compiler/back/top/anormcode/anormcode-namedtypevar-vs-debruijntypevar-forms.pkg
        #
        fun tc_named_typevar_elimination_thunk ()                               # Evaluating the thunk allocates a new dictionary.
            =
            tc_named_typevar_elimination
            where

                dictionary = REF (uniqtype_dictionary::empty);
                #
                fun tc_named_typevar_elimination  s  depth  type
                    = 
                    case (hut::get_free_named_variables_in_uniqtype  type)   
                        #
                        [] => type;                   #  nothing to elim 
                        #
                        _  =>
                            {   # Encode the type and
                                # the depth for memoization
                                # using make_ith_in_typeseq_uniqtype:
                                #
                                tycdepth = make_ith_in_typeseq_uniqtype (type, depth);

                                case (uniqtype_dictionary::get (*dictionary, tycdepth))
                                    #   
                                    THE t => t;                 #  hit! 
                                    #
                                    NULL =>                  #  must recompute
                                        { 
                                            r = tc_named_typevar_elimination  s  depth;                 # Default recursive invoc. 
                                            rs = map r;         # Recursive invocation on list.

                                            t = case (hut::uniqtype_to_type type)   
                                                    #
                                                    hut::type::DEBRUIJN_TYPEVAR  _ => type;
                                                    hut::type::BASETYPE _ => type;
                                                    #   
                                                    hut::type::TYPEFUN   (tks, t) =>  make_typefun_uniqtype (tks, tc_named_typevar_elimination s (di::next depth) t);
                                                    hut::type::APPLY_TYPEFUN (t, ts) =>  make_apply_typefun_uniqtype (r t, rs ts);
                                                    hut::type::TYPESEQ ts        =>  make_typeseq_uniqtype (rs ts);
                                                    #
                                                    hut::type::ITH_IN_TYPESEQ (t, i)   =>  make_ith_in_typeseq_uniqtype (r t, i);
                                                    hut::type::SUM ts        =>  make_sum_uniqtype (rs ts);
                                                    #
                                                    hut::type::TUPLE (rf, ts)      =>  make_tuple_uniqtype (rs ts);
                                                    hut::type::ARROW (ff, ts, ts') =>  make_arrow_uniqtype (ff, rs ts, rs ts');
                                                    hut::type::PARROW (t, t')      =>  make_lambdacode_arrow_uniqtype (r t, r t');
                                                    #
                                                    hut::type::BOXED t             =>  make_boxed_uniqtype (r t);
                                                    hut::type::ABSTRACT t          =>  make_abstract_uniqtype (r t);
                                                    hut::type::FATE ts     =>  make_uniqtype_fate (rs ts);
                                                    #   
                                                    hut::type::RECURSIVE ((i, t, ts), j)
                                                        =>
                                                        make_recursive_uniqtype ((i, r t, rs ts), j);

                                                    hut::type::NAMED_TYPEVAR tvar
                                                        =>   
                                                        case (s (tvar, depth))
                                                            #
                                                            THE t =>  t;
                                                            NULL  =>  type;
                                                        esac;

                                                    hut::type::EXTENSIBLE_TOKEN (tok, t)
                                                        =>
                                                        hut::type_to_uniqtype (hut::type::EXTENSIBLE_TOKEN (tok, r t));


                                                    hut::type::INDIRECT_TYPE_THUNK     _  =>  bug "unexpected TC_INDIRECT in tc_named_typevar_elimination";
                                                    hut::type::TYPE_CLOSURE      _  =>  bug "unexpected TC_CLOSURE in tc_named_typevar_elimination";
                                                esac;

                                            dictionary := uniqtype_dictionary::set (*dictionary, tycdepth, t);

                                            t;
                                    };
                                esac;
                            };
                    esac;                                       # tc_named_typevar_elimination 
            end;

        # Used (only) in                src/lib/compiler/back/top/anormcode/anormcode-namedtypevar-vs-debruijntypevar-forms.pkg
        #
        fun lt_named_typevar_elimination_thunk ()                               # Evaluating the thunk allocates a new dictionary.
            =
            lt_named_typevar_elimination
            where

                dictionary =  REF (uniqtypoid_dictionary::empty);

                tc_named_typevar_elimination =  tc_named_typevar_elimination_thunk();                           # Evaluating the thunk allocates a new dictionary.
                #
                fun lt_named_typevar_elimination  s  depth  lambda_type
                    = 
                    case (hut::get_free_named_variables_in_uniqtypoid  lambda_type)   
                        #
                        [] => lambda_type;                   #  nothing to elim 
                        #
                        _  => {
                                # Encode the hut::Uniqtypoid and depth info
                                # using TYPE_CLOSURE
                                # (only first 2 args are useful)
                                #
                                ltydepth
                                    =
                                    hut::typoid_to_uniqtypoid
                                      (
                                        hut::typoid::TYPE_CLOSURE (lambda_type, depth, 0, hut::empty_uniqtype_dictionary)
                                      );

                                case (uniqtypoid_dictionary::get (*dictionary, ltydepth))
                                    #
                                    THE t => t;                 # Hit.
                                    #
                                    NULL =>                     # Must recompute.
                                        t
                                        where
                                            r = lt_named_typevar_elimination s depth;                   #  Default recursive invoc. 
                                            rs = map r;          #  recursive invocation on list 

                                            t = case (hut::uniqtypoid_to_typoid  lambda_type)   
                                                    #
                                                    hut::typoid::TYPE t       =>  make_type_uniqtypoid (tc_named_typevar_elimination s depth t);
                                                    hut::typoid::PACKAGE     ts      =>  make_package_uniqtypoid (rs ts);
                                                    #
                                                    hut::typoid::GENERIC_PACKAGE  (ts,  ts') =>  make_generic_package_uniqtypoid (rs ts, rs ts');
                                                    hut::typoid::TYPEAGNOSTIC     (tks, ts)  =>  make_typeagnostic_uniqtypoid (tks, map (lt_named_typevar_elimination s (di::next depth)) ts);
                                                    hut::typoid::FATE                 ts   =>  make_uniqtypoid_fate (rs ts);
                                                    #
                                                    hut::typoid::INDIRECT_TYPE_THUNK _       =>  bug "unexpected INDIRECT_TYPE_THUNK in lt_named_typevar_elimination";
                                                    hut::typoid::TYPE_CLOSURE        _       =>  bug "unexpected TYPE_CLOSURE in lt_named_typevar_elimination";
                                                esac;

                                            dictionary :=  uniqtypoid_dictionary::set (*dictionary, ltydepth, t);
                                        end;
                                esac;
                            };
                    esac;                        # fun lt_named_typevar_elimination 

            end;                                 # fun lt_named_typevar_elimination_thunk 

        ############################################################

        Smap = List ((tmp::Codetemp, hut::Uniqtype));

        # Is the intersection of two
        # sorted lists non-NIL?
        # 
        fun intersection_non_empty (NIL, _: List( tmp::Codetemp ))
                =>
                FALSE;

            intersection_non_empty(_, NIL)
                =>
                FALSE;

            intersection_non_empty (s1 as (h1: tmp::Codetemp, _) ! t1, s2 as h2 ! t2)
                =>
                case (int::compare (h1, h2))   
                    #   
                    LESS    => intersection_non_empty (t1, s2);
                    GREATER => intersection_non_empty (s1, t2);
                    EQUAL   => TRUE;
                esac;
        end;
        #
        fun search_subst (tv: tmp::Codetemp, s)
            = 
            h s
            where
                fun h [] =>   NULL;
                    #
                    h ((tv': tmp::Codetemp, type) ! s)
                        => 
                        case (int::compare (tv, tv'))   
                            #
                            LESS    =>  NULL;
                            GREATER =>  h s;
                            EQUAL   =>  THE type;
                        esac;
                end;
            end;
        #
        fun tc_nvar_subst_fn ()
            =
            tc_nvar_subst
            where
                dictionary = REF (uniqtype_dictionary::empty);
                #
                fun tc_nvar_subst subst
                    =
                    loop
                    where
                        fun loop type
                            =
                            # Check if substitution overlaps
                            # with free vars list:
                            #
                            case (intersection_non_empty (subst, hut::get_free_named_variables_in_uniqtype type))   
                                #
                                FALSE => type;               #  nothing to subst 
                                #
                                TRUE => 
                                    # Next check the memoization table:
                                    #
                                    case (uniqtype_dictionary::get (*dictionary, type))
                                        #
                                        THE t => t;                     # Hit.
                                        #
                                        NULL =>                         # Must recompute.
                                            t
                                            where
                                                t = case (hut::uniqtype_to_type type)   
                                                        #
                                                        hut::type::NAMED_TYPEVAR tv
                                                            => 
                                                            case (search_subst (tv, subst))
                                                                #
                                                                THE t =>  t; 
                                                                NULL  =>  type;
                                                            esac;
                                                        #
                                                        hut::type::DEBRUIJN_TYPEVAR  _ => type;
                                                        hut::type::BASETYPE _ => type;
                                                        #
                                                        hut::type::TYPEFUN   (tks, t) =>  make_typefun_uniqtype (tks, loop t);
                                                        hut::type::APPLY_TYPEFUN (t, ts) =>  make_apply_typefun_uniqtype (loop t, map loop ts);
                                                        #
                                                        hut::type::TYPESEQ ts      =>  make_typeseq_uniqtype (map loop ts);
                                                        hut::type::ITH_IN_TYPESEQ (t, i) =>  make_ith_in_typeseq_uniqtype (loop t, i);
                                                        hut::type::SUM ts      =>  make_sum_uniqtype (map loop ts);
                                                        #
                                                        hut::type::RECURSIVE ((i, t, ts), j)
                                                            =>
                                                            make_recursive_uniqtype ((i, loop t, map loop ts), j);
                                                        #
                                                        hut::type::TUPLE (rf, ts)      =>  make_tuple_uniqtype (map loop ts);
                                                        hut::type::ARROW (ff, ts, ts') =>  make_arrow_uniqtype (ff, map loop ts, map loop ts');
                                                        hut::type::PARROW (t, t')      =>  make_lambdacode_arrow_uniqtype (loop t, loop t');
                                                        #
                                                        hut::type::BOXED        t  =>  make_boxed_uniqtype (loop t);
                                                        hut::type::ABSTRACT     t  =>  make_abstract_uniqtype (loop t);
                                                        hut::type::FATE ts =>  make_uniqtype_fate (map loop ts);

                                                        hut::type::EXTENSIBLE_TOKEN (tok, t)
                                                             =>
                                                             hut::type_to_uniqtype (hut::type::EXTENSIBLE_TOKEN (tok, loop t));

                                                        hut::type::INDIRECT_TYPE_THUNK _ => bug "unexpected TC_INDIRECT in substTypeConstructor";
                                                        hut::type::TYPE_CLOSURE  _ => bug "unexpected TC_CLOSURE in substTypeConstructor";
                                                    esac;

                                                # Update memoization table:
                                                # 
                                                dictionary :=  uniqtype_dictionary::set (*dictionary, type, t);
                                            end;
                                     esac;

                            esac;
                end;                    # fun tc_nvar_subst 
            end;                        # fun tc_nvar_subst_fn 
        #
        fun lt_nvar_subst_fn ()
            =
            lt_nvar_subst
            where
                dictionary = REF (uniqtypoid_dictionary::empty);

                tc_nvar_subst' = tc_nvar_subst_fn();
                #
                fun lt_nvar_subst subst
                    =
                    loop
                    where

                        tc_nvar_subst = tc_nvar_subst' subst;
                        #
                        fun loop lambda_type
                            =
                            # First check if there are
                            # any free type variables:
                            #
                            case (intersection_non_empty (subst, hut::get_free_named_variables_in_uniqtypoid lambda_type))   
                                #
                                FALSE => lambda_type;                  #  nothing to subst 
                                #
                                TRUE => 
                                    # Next, check the memoization table:
                                    # 
                                    case (uniqtypoid_dictionary::get (*dictionary, lambda_type))
                                        #
                                        THE t => t;             # A hit! 
                                        #
                                        NULL =>         # Must recompute>
                                            t
                                            where
                                                t = case (hut::uniqtypoid_to_typoid lambda_type)   
                                                        #
                                                        hut::typoid::TYPE t      =>  make_type_uniqtypoid (tc_nvar_subst t);
                                                        #
                                                        hut::typoid::PACKAGE ts                =>  make_package_uniqtypoid (map loop ts);
                                                        hut::typoid::GENERIC_PACKAGE (ts, ts') =>  make_generic_package_uniqtypoid (map loop ts, map loop ts');
                                                        #
                                                        hut::typoid::TYPEAGNOSTIC    (tks, ts) =>  make_typeagnostic_uniqtypoid (tks, map loop ts);
                                                        hut::typoid::FATE                  ts  =>  make_uniqtypoid_fate (map loop ts);
                                                        #
                                                        hut::typoid::INDIRECT_TYPE_THUNK _     =>  bug "unexpected INDIRECT_TYPE_THUNK in lt_named_typevar_elimination";
                                                        hut::typoid::TYPE_CLOSURE        _     =>  bug "unexpected TYPE_CLOSURE in lt_named_typevar_elimination";
                                                    esac;

                                                # Update memoization table:
                                                #
                                                dictionary :=  uniqtypoid_dictionary::set (*dictionary, lambda_type, t);
                                            end;
                                     esac;

                            esac;
                    end;                                # fun lt_nvar_subst 
            end;                                        # fun lt_nvar_subst_fn 

        ############################################################

        # Building up a typeagnostic type by abstracting over a 
        # list of named vars 

        Tvoffs = List ((tmp::Codetemp, Int));
        #
        fun intersect (NIL, _: List( tmp::Codetemp ))
                =>
                NIL;

            intersect(_, NIL)
                =>
                NIL;

            intersect (s1 as (h1: tmp::Codetemp, n) ! t1, s2 as h2 ! t2)
                =>
                case (int::compare (h1, h2))   
                    #   
                    LESS    => intersect (t1, s2);
                    GREATER => intersect (s1, t2);
                    EQUAL   => (h1, n) ! intersect (t1, t2);
                esac;
        end;

        #  s_iter = compile_statistics::makeStat "Cvt Iterations"      
        #  s_hits = compile_statistics::makeStat "Cvt Hits in dictionary"    
        #  s_cuts = compile_statistics::makeStat "Cvt Freevar cutoffs" 

        #  s_tvoffs = compile_statistics::makeStat "Cvt tvoffs length" 
        #  s_nvars = compile_statistics::makeStat "Cvt free nvars length" 
        #
        fun tc_nvar_cvt_fn ()
            =
            tc_nvar_cvt
            where

                dictionary = REF (uniqtype_dictionary::empty);
                #
                fun tc_nvar_cvt (tvoffs: Tvoffs) d type
                    = 
                    #  Compile_statistics::addStat s_iter 1; 
                    #  Compile_statistics::addStat s_tvoffs (length tvoffs); 
                    #  Compile_statistics::addStat s_nvars (length (hut::freeNamedVariablesInTypeConstructor type)); 
                    #  Check if substitution overlaps with free vars list 
                    #   
                    case (intersect (tvoffs, hut::get_free_named_variables_in_uniqtype type))   
                        #
                        [] => (#  Compile_statistics::addStat s_cuts 1; 
                               type           #  nothing to convert 
                               );

                        tvoffs
                            =>
                            {
                                # Encode the type
                                # and the depth for memoization
                                # using make_ith_in_typeseq_uniqtype:
                                #
                                tycdepth = make_ith_in_typeseq_uniqtype (type, d);

                                case (uniqtype_dictionary::get (*dictionary, tycdepth))
                                    #
                                    THE t => (#  Compile_statistics::addStat s_hits 1; 
                                              t                 # Hit.
                                              );
                                    #
                                    NULL =>                     # Must recompute.
                                       t
                                       where    
                                           r = tc_nvar_cvt tvoffs d; #  Default recursive invoc. 

                                           rs = map r;          #  recursive invocation on list 

                                           t =  case (hut::uniqtype_to_type  type)
                                                    #
                                                    hut::type::NAMED_TYPEVAR tvar
                                                        =>
                                                        case (search_subst (tvar, tvoffs))
                                                            #
                                                            THE i =>  make_debruijn_typevar_uniqtype (d, i);
                                                            NULL  =>  type;
                                                        esac;
                                                    #
                                                    hut::type::DEBRUIJN_TYPEVAR _        => type;
                                                    hut::type::BASETYPE _       => type;
                                                    hut::type::TYPEFUN (tks, t)  => make_typefun_uniqtype (tks, tc_nvar_cvt tvoffs (di::next d) t);
                                                    #
                                                    hut::type::APPLY_TYPEFUN (t, ts) => make_apply_typefun_uniqtype (r t, rs ts);
                                                    hut::type::TYPESEQ ts           => make_typeseq_uniqtype (rs ts);
                                                    hut::type::ITH_IN_TYPESEQ (t, i) => make_ith_in_typeseq_uniqtype (r t, i);

                                                    hut::type::SUM ts                   => make_sum_uniqtype (rs ts);
                                                    hut::type::RECURSIVE ((i, t, ts), j) => make_recursive_uniqtype ((i, r t, rs ts), j);
                                                    hut::type::TUPLE (rf, ts)            => make_tuple_uniqtype (rs ts);

                                                    hut::type::ARROW (ff, ts, ts')  => make_arrow_uniqtype (ff, rs ts, rs ts');
                                                    hut::type::PARROW (t, t')       => make_lambdacode_arrow_uniqtype (r t, r t');
                                                    hut::type::BOXED t              => make_boxed_uniqtype (r t);

                                                    hut::type::ABSTRACT t                => make_abstract_uniqtype (r t);
                                                    hut::type::EXTENSIBLE_TOKEN (tok, t) => hut::type_to_uniqtype (hut::type::EXTENSIBLE_TOKEN (tok, r t));
                                                    hut::type::FATE ts                  => make_uniqtype_fate (rs ts);

                                                    hut::type::INDIRECT_TYPE_THUNK _ => bug "unexpected TC_INDIRECT in tc_nvar_cvt";
                                                    hut::type::TYPE_CLOSURE _  => bug "unexpected TC_CLOSURE in tc_nvar_cvt";
                                                esac;

                                           dictionary := uniqtype_dictionary::set (*dictionary, tycdepth, t);
                                       end;
                                esac;
                            };
                    esac;                       # fun tc_nvar_cvt 
            end;                                # fun tc_nvar_cvt_fn 

        #
        fun lt_nvar_cvt_fn ()
            =
            lt_nvar_cvt
            where

                dictionary = REF (uniqtypoid_dictionary::empty);

                tc_nvar_cvt = tc_nvar_cvt_fn();
                #
                fun lt_nvar_cvt tvoffs d lambda_type
                    = 
                    # Check if substitution overlaps
                    # with free vars list:
                    #
                    case (intersect (tvoffs, hut::get_free_named_variables_in_uniqtypoid lambda_type))   
                        #
                        [] => lambda_type;                #  nothing to convert 
                        #
                        tvoffs => {
                            # encode the lambdaType and depth info using TYPE_CLOSURE
                            # (only first 2 args are useful)
                            ltydepth = hut::typoid_to_uniqtypoid (hut::typoid::TYPE_CLOSURE (lambda_type, d, 0, hut::empty_uniqtype_dictionary));

                            case (uniqtypoid_dictionary::get (*dictionary, ltydepth))
                                #
                                THE t => t;                 #  hit! 
                                #
                                NULL =>                 #  must recompute 
                                    t
                                    where

                                        r = lt_nvar_cvt tvoffs d;               # Default recursive invoc. 
                                        rs = map r;                     # Recursive invocation on list.

                                        t = case (hut::uniqtypoid_to_typoid lambda_type)   
                                                #
                                                hut::typoid::TYPE t
                                                    => 
                                                    make_type_uniqtypoid (tc_nvar_cvt tvoffs d t);
                                                #
                                                hut::typoid::PACKAGE ts                =>  make_package_uniqtypoid (rs ts);
                                                hut::typoid::GENERIC_PACKAGE (ts, ts') =>  make_generic_package_uniqtypoid (rs ts, rs ts');
                                                #
                                                hut::typoid::TYPEAGNOSTIC (tks, ts)
                                                    => 
                                                    make_typeagnostic_uniqtypoid (tks, 
                                                               map (lt_nvar_cvt tvoffs (di::next d)) ts);
                                                #
                                                hut::typoid::FATE ts
                                                    => 
                                                    make_uniqtypoid_fate (rs ts);
                                                #
                                                hut::typoid::INDIRECT_TYPE_THUNK _ => bug "unexpected INDIRECT_TYPE_THUNK in lt_nvar_cvt";
                                                hut::typoid::TYPE_CLOSURE       _ => bug "unexpected TYPE_CLOSURE in lt_nvar_cvt";
                                            esac;

                                        dictionary := uniqtypoid_dictionary::set (*dictionary, ltydepth, t);
                                    end;
                            esac;
                        };
                    esac;               # fun lt_nvar_cvt 
            end;                        # fun lt_nvar_cvt_fn 

        # Make a type abstraction
        # from nvar to lambda type: 
        #
        fun lt_nvpoly (tvks, lt)
            = 
            {   fun frob ((tv, k) ! tvks, n, ks, tvoffs)
                        =>
                        frob (tvks, n+1, k ! ks, (tv, n) ! tvoffs);

                    frob ([], _, ks, tvoffs)
                        =>
                        (reverse ks, reverse tvoffs);
                end;


                my (ks, tvoffs)
                    =
                    frob (tvks, 0, [], []);

                #
                fun cmp ((tvar1, _), (tvar2, _))
                    =
                    tvar1 > tvar2;


                tvoffs =  lms::sort_list  cmp  tvoffs;

                # Temporarily gen() 
                #
                lt_subst = lt_nvar_cvt_fn() tvoffs (di::next di::top);
            
                make_typeagnostic_uniqtypoid (ks, map lt_subst lt);
            };

    };                                                                                  #  package highcode 
end;                                                                                    #  top-level stipulate


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext