PreviousUpNext

15.4.652  src/lib/compiler/front/typer/modules/api-match-g.pkg

## api-match-g.pkg

# Compiled by:
#     src/lib/compiler/front/typer/typer.sublib

# The center of the typechecker is
#
#     src/lib/compiler/front/typer/main/type-package-language-g.pkg
#
# -- see it for a higher-level overview.
# It calls us to do specialized typechecking
# of apis and generics.



###              "If language is not correct,
###                   then what is said is not what is meant.
###               If what is said is not what is meant,
###                   then what ought to be done remains undone."
###
###                                   -- Kong Fu Zi
###                                      (aka "Confucius")


stipulate
    package di  =  debruijn_index;                              # debruijn_index                        is from   src/lib/compiler/front/typer/basics/debruijn-index.pkg
    package ds  =  deep_syntax;                                 # deep_syntax                           is from   src/lib/compiler/front/typer-stuff/deep-syntax/deep-syntax.pkg
    package ip  =  inverse_path;                                # inverse_path                          is from   src/lib/compiler/front/typer-stuff/basics/symbol-path.pkg
    package lnd =  line_number_db;                              # line_number_db                        is from   src/lib/compiler/front/basics/source/line-number-db.pkg
    package mld =  module_level_declarations;                   # module_level_declarations             is from   src/lib/compiler/front/typer-stuff/modules/module-level-declarations.pkg
    package mp  =  stamppath;                                   # stamppath                             is from   src/lib/compiler/front/typer-stuff/modules/stamppath.pkg
    package spc =  stamppath_context;                           # stamppath_context                     is from   src/lib/compiler/front/typer-stuff/modules/stamppath-context.pkg
    package sta =  stamp;                                       # stamp                                 is from   src/lib/compiler/front/typer-stuff/basics/stamp.pkg
    package syx =  symbolmapstack;                              # symbolmapstack                        is from   src/lib/compiler/front/typer-stuff/symbolmapstack/symbolmapstack.pkg
    package trj =  typer_junk;                                  # typer_junk                            is from   src/lib/compiler/front/typer/main/typer-junk.pkg
herein

    api Api_Match {

        package expand_generic
        :       Expand_Generic;                                 # Expand_Generic                        is from   src/lib/compiler/front/typer/modules/expand-generic-g.pkg


        # These four functions are only called
        # inside type-package-language.pkg.


        # thin_package() and cast_package() are a pair.
        #
        # Essentially, the first removes mld::A_PACKAGE.an_api.elements
        # which are not declared in the constraining
        # API, while the second converts mld::A_PACKAGE.an_api.elements
        # to abstract form as required by the constraining API.
        #    
        # We apply both in order to implement strong
        # sealing (SML ":>", Mythryl ":") -- see
        #
        #     type_constrained_package
        #
        # in  src/lib/compiler/front/typer/main/type-package-language-g.pkg
        #
        # To implement weak sealing
        # (SML ":",  Mythry ": (weak) ")
        # we call the first but not the second.


        thin_package:
                            {    constrained_package:        mld::Package,                      # Check this package
                                 constraining_api:           mld::Api,                          # against this API.

                                 package_expression:         mld::Package_Expression,

                                 module_stamp_or_null:       Null_Or( sta::Stamp ),
                                 debruijn_depth:             di::Debruijn_Depth,
                                 typerstore:                 mld::Typerstore,

                                 inverse_path:               ip::Inverse_Path,
                                 symbolmapstack:             syx::Symbolmapstack,

                                 source_code_region:         lnd::Source_Code_Region,
                                 per_compile_stuff:           trj::Per_Compile_Stuff
                             }
                             ->
                             {   result_declaration:         ds::Declaration,
                                 result_package:             mld::Package,
                                 coerced_package_expression: mld::Package_Expression    # a mld::COERCED_PACKAGE coercing original package_expression to proper api.
                             };

        cast_package:
                             {   constrained_package:        mld::Package,
                                 constraining_api:           mld::Api,

                                 package_expression:         mld::Package_Expression,
                                 debruijn_depth:             di::Debruijn_Depth,

                                 typerstore:                 mld::Typerstore,
                                 inverse_path:               ip::Inverse_Path,

                                 symbolmapstack:             syx::Symbolmapstack,
                                 source_code_region:         lnd::Source_Code_Region,
                                 per_compile_stuff:           trj::Per_Compile_Stuff
                             }
                             -> 
                             {   result_declaration:         ds::Declaration,
                                 result_package:             mld::Package,
                                 result_expression:          mld::Package_Expression
                             };




         match_generic:      {   an_api:                     mld::Generic_Api,
                                 a_generic:                  mld::Generic,
                                 generic_expression:         mld::Generic_Expression,

                                 debruijn_depth:             di::Debruijn_Depth,
                                 typerstore:                 mld::Typerstore,
                                 inverse_path:               ip::Inverse_Path,

                                 symbolmapstack:             syx::Symbolmapstack,
                                 source_code_region:         lnd::Source_Code_Region,
                                 per_compile_stuff:           trj::Per_Compile_Stuff
                             }
                             ->
                             {   result_declaration:         ds::Declaration,
                                 result_generic:             mld::Generic,
                                 result_expression:          mld::Generic_Expression
                             };

         apply_generic:    {     a_generic:                  mld::Generic,
                                 generic_expression:         mld::Generic_Expression,
                                 arg_package:                mld::Package,

                                 arg_expression:             mld::Package_Expression,
                                 module_stamp_or_null:       Null_Or( sta::Stamp ),
                                 debruijn_depth:             di::Debruijn_Depth,

                                 stamppath_context:          spc::Context,                                
                                 symbolmapstack:             syx::Symbolmapstack,
                                 inverse_path:               ip::Inverse_Path,

                                 source_code_region:         lnd::Source_Code_Region,
                                 per_compile_stuff:           trj::Per_Compile_Stuff
                             }
                             ->
                             {   result_declaration:         ds::Declaration,
                                 result_package:             mld::Package,
                                 result_expression:          mld::Package_Expression
                             };


         debugging:  Ref(  Bool );
         show_apis:  Ref(  Bool );

    };                                                                                  # Api Api_Match
end;                                                                                    # stipulate

#  We use a generic to factor out dependencies on highcode:
#
# This generic is invoked in
#     src/lib/compiler/front/semantic/modules/api-match.pkg
#

stipulate
    package di  =  debruijn_index;                              # debruijn_index                        is from   src/lib/compiler/front/typer/basics/debruijn-index.pkg
    package ds  =  deep_syntax;                                 # deep_syntax                           is from   src/lib/compiler/front/typer-stuff/deep-syntax/deep-syntax.pkg
    package ep  =  stamppath;                                   # stamppath                             is from   src/lib/compiler/front/typer-stuff/modules/stamppath.pkg
    package epc =  stamppath_context;                           # stamppath_context                     is from   src/lib/compiler/front/typer-stuff/modules/stamppath-context.pkg
    package err =  error_message;                               # error_message                         is from   src/lib/compiler/front/basics/errormsg/error-message.pkg
    package id  =  inlining_data;                               # inlining_data                         is from   src/lib/compiler/front/typer-stuff/basics/inlining-data.pkg
    package ip  =  inverse_path;                                # inverse_path                          is from   src/lib/compiler/front/typer-stuff/basics/symbol-path.pkg
    package lms =  list_mergesort;                              # list_mergesort                        is from   src/lib/src/list-mergesort.pkg
    package lnd =  line_number_db;                              # line_number_db                        is from   src/lib/compiler/front/basics/source/line-number-db.pkg
    package mj  =  module_junk;                                 # module_junk                           is from   src/lib/compiler/front/typer-stuff/modules/module-junk.pkg
    package mld =  module_level_declarations;                   # module_level_declarations             is from   src/lib/compiler/front/typer-stuff/modules/module-level-declarations.pkg
    package mp  =  stamppath;                                   # stamppath                             is from   src/lib/compiler/front/typer-stuff/modules/stamppath.pkg
    package pp  =  standard_prettyprinter;                      # standard_prettyprinter                is from   src/lib/prettyprint/big/src/standard-prettyprinter.pkg
    package spc =  stamppath_context;                           # stamppath_context                     is from   src/lib/compiler/front/typer-stuff/modules/stamppath-context.pkg
    package sta =  stamp;                                       # stamp                                 is from   src/lib/compiler/front/typer-stuff/basics/stamp.pkg
    package sxe =  symbolmapstack_entry;                        # symbolmapstack_entry                  is from   src/lib/compiler/front/typer-stuff/symbolmapstack/symbolmapstack-entry.pkg
    package sy  =  symbol;                                      # symbol                                is from   src/lib/compiler/front/basics/map/symbol.pkg
    package syp =  symbol_path;                                 # symbol_path                           is from   src/lib/compiler/front/typer-stuff/basics/symbol-path.pkg
    package syx =  symbolmapstack;                              # symbolmapstack                        is from   src/lib/compiler/front/typer-stuff/symbolmapstack/symbolmapstack.pkg
    package tdt =  type_declaration_types;                      # type_declaration_types                is from   src/lib/compiler/front/typer-stuff/types/type-declaration-types.pkg
    package tj  =  type_junk;                                   # type_junk                             is from   src/lib/compiler/front/typer-stuff/types/type-junk.pkg
    package trj =  typer_junk;                                  # typer_junk                            is from   src/lib/compiler/front/typer/main/typer-junk.pkg
    package tro =  typerstore;                                  # typerstore                            is from   src/lib/compiler/front/typer-stuff/modules/typerstore.pkg
    package tyd =  typer_debugging;                             # typer_debugging                       is from   src/lib/compiler/front/typer/main/typer-debugging.pkg
    package upl =  unparse_package_language;                    # unparse_package_language              is from   src/lib/compiler/front/typer/print/unparse-package-language.pkg
    package vac =  variables_and_constructors;                  # variables_and_constructors            is from   src/lib/compiler/front/typer-stuff/deep-syntax/variables-and-constructors.pkg
    package vh  =  varhome;                                     # varhome                               is from   src/lib/compiler/front/typer-stuff/basics/varhome.pkg

    Pp = pp::Pp;
herein

    generic package api_match_g (package expand_generic:  Expand_Generic;)              # Expand_Generic                        is from   src/lib/compiler/front/typer/modules/expand-generic-g.pkg
                                                                                        # expand_generic                        is from   src/lib/compiler/front/semantic/modules/expand-generic.pkg
    : (weak)  Api_Match                                                                 # Api_Match                             is from   src/lib/compiler/front/typer/modules/api-match-g.pkg

    {

        # Export our parameter for client packages:
        #
        package expand_generic = expand_generic;

        # A local abbreviation:
        #
        package gxs = expand_generic::generics_expansion_junk;

        exception BAD_NAMING;

        no_undo_log = REF (NULL: Null_Or(List(Void -> Void)));                          # This REF will never get set to anything else, so it is harmless.

        show_apis = REF FALSE;
        debugging = typer_control::api_match_debugging;                                 #  eval:   set_control "typechecker::api_match_debugging" "TRUE";

        # To use the above "debugging" flag you might (say) do
        #
        #     linux$ cd src/app/tut/test
        #     linux$ touch test.pkg
        #     linux$ my
        #     eval:  set_control "typechecker::api_match_debugging" "TRUE";
        #     eval:  make "test.lib";
        #
        # This will spew debug printouts of various datastructures
        # as the code in this file runs.


        say = control_print::say;
        #
        fun if_debugging_say (msg: String)
            =
            if   *debugging       say msg;   say "\n";   fi;


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

        nth = list::nth;
        #
        fun for' l f
            =
            apply f l;
        #
        fun unwrap_typecon_entry (mld::TYPE_ENTRY x) =>   x;
            unwrap_typecon_entry _                  =>   bug "unwrap_typecon_entry";
        end;

        # Given a list of symbols created by
        #     src/lib/compiler/front/basics/map/symbol.pkg
        # return "a, b, c" or such:
        #
        fun symbols_to_string [ ] =>  "";
            symbols_to_string [n] =>  sy::name n;

            symbols_to_string (n ! r)
                =>
                cat (sy::name n ! fold_backward
                                     (\\ (n, b) = (", " ! sy::name n ! b))
                                     []
                                     r);
        end;

        bogus_type =  tdt::UNDEFINED_TYPOID; 

        # Bogus coercion expressions returned by the matching functions.
        # These should never be evaluated. 
        #
        bogus_package_expression =   mld::VARIABLE_PACKAGE [];
        bogus_generic_expression =   mld::VARIABLE_GENERIC [];
        #
        fun if_debugging_show_package (msg, pkg)
            =
            tyd::with_internals (\\ () =  tyd::debug_print
                                             debugging
                                             ( msg,
                                               (\\ pps =  \\ pkg =  upl::unparse_package pps (pkg, syx::empty, 100)),
                                               pkg
                                             )
                               );
        #
        fun exception_representation (vh::EXCEPTION _, varhome) =>  vh::EXCEPTION varhome;
            exception_representation _                           =>  bug "unexpected Valcon_Form in exception_representation";
        end;
        #
        fun is_named (THE _) =>  TRUE;
            is_named _       =>  FALSE;
        end;

        anonymous_package_symbol =  sy::make_package_symbol  "<anonymous_package>";
        anonymous_generic_symbol =  sy::make_generic_symbol  "<anonymous_generic>";

        generic_api_parameter_typechecked_package_symbol
            =
            sy::make_package_symbol
                "<generic_api_parameter_evaluation>";
        #
        fun ident _ = ();



        #  Match an abstract version of a type with its actual version.
        #  Return TRUE and the new instantiations if package type > api type 
        #
        fun try_unifying_pkg_with_api_type
            ( type_per_api,
              type_per_pkg,
              inlining_data
            )
            :
            ( List( tdt::Typoid      ),
              List( tdt::Typevar_Ref ),
              tdt::Typoid,
              Bool                      # TRUE iff the two match.
            )
            =
            {   type_per_pkg =  tj::drop_resolved_typevars type_per_pkg;                        # Drop redundant RESOLVED_TYPEVAR indirections.
                type_per_api =  tj::drop_resolved_typevars type_per_api;                        # Drop redundant RESOLVED_TYPEVAR indirections.

                (tj::instantiate_if_typescheme  (type_per_pkg, syx::empty, [ "try_unifying_pkg_with_api_type" ])) ->   (type_per_pkg', fresh_meta_typevars_for_pkg);
                (tj::instantiate_if_typescheme  (type_per_api, syx::empty, [ "try_unifying_pkg_with_api_type" ])) ->   (type_per_api', fresh_meta_typevars_for_api);

                paired_lists::apply  unify  (fresh_meta_typevars_for_pkg, fresh_meta_typevars_for_api)
                where
                    fun unify (type1, type2)
                        =
                        unify_typoids::unify_typoids ("1", "2", type1, type2, ["try_unifying_pkg_with_api_type"], no_undo_log );
                end;

                # This is a gross hack. Inlining-information such as primops 
                # (or inline-able expressions) are propagated through api
                # matching. However, their types may change. The following code
                # is to figure out the proper type application arguments, insttys.
                # The typechecker has a similar hack. We will clean this up in the
                # future (ZHONG).
                #
                # Change: The hack is gone, but I am not sure whether the code
                # below could be further simplified.  (inline_baseop now has mandatory
                # type information, and this type information is always correctly
                # provided by base-types-and-ops.pkg.)  (Blume, 1/2001)


                types = case (gxs::param::inlining_data_to_my_type  inlining_data)
                            #
                            THE type_per_inlining_data
                                =>
                                {   (tj::instantiate_if_typescheme  (type_per_inlining_data, syx::empty, [ "try_unifying_pkg_with_api_type" ]))
                                        ->
                                        (type_per_inlining_data', fresh_meta_typevars_for_inlining_data);

                                    unify_typoids::unify_typoids ("1", "2", type_per_inlining_data', type_per_pkg', ["try_unifying_pkg_with_api_type"], no_undo_log)
                                    except
                                        _ = ();

                                    fresh_meta_typevars_for_inlining_data;
                                };

                            NULL => fresh_meta_typevars_for_pkg;

                        esac;

                types_matched
                    =
                    {   unify_typoids::unify_typoids ("1", "2", type_per_pkg', type_per_api', ["try_unifying_pkg_with_api_type"], no_undo_log);
                        TRUE;
                    }
                    except
                        _ = FALSE;

                typevar_refs
                    =
                    map tj::typevar_of_typoid
                        fresh_meta_typevars_for_pkg;                                            # Q: Should I use fresh_meta_typevars_for_api here instead, why fresh_meta_typevars_for_pkg?
                                                                                # A: They've been unified, it makes no difference -- they will be identical at this point.      

                (types, typevar_refs, type_per_api', types_matched);
            };                                                                  # fun try_unifying_pkg_with_api_type



        # This function does about 80%
        # of what the above function does.
        #
        # This one  gets used in thin_package();
        # the above gets used in cast_package().
        #
        # This one gets called only when the pkg and api types are known to match;
        # the above gets called when this is not known, hence returns that information.
        #
        fun unify_pkg_with_api_type { type_per_api, type_per_pkg, inlining_data }
            :
            ( List( tdt::Typoid      ),
              List( tdt::Typevar_Ref )
            )
            = 
            {   type_per_pkg =  tj::drop_resolved_typevars  type_per_pkg;                                       # Drop redundant RESOLVED_TYPEVAR indirections.
                #
                (tj::instantiate_if_typescheme  (type_per_pkg, syx::empty, [ "unify_pkg_with_api_type" ])) ->   (type_per_pkg', fresh_meta_typevars_for_pkg);
                (tj::instantiate_if_typescheme  (type_per_api, syx::empty, [ "unify_pkg_with_api_type" ])) ->   (type_per_api', fresh_meta_typevars_for_api);

                types = case (gxs::param::inlining_data_to_my_type  inlining_data)
                            #
                            THE type_per_inlining_data
                                =>
                                {   (tj::instantiate_if_typescheme   (type_per_inlining_data, syx::empty, [ "unify_pkg_with_api_type" ]))
                                        ->
                                        (type_per_inlining_data', fresh_meta_typevars_for_inlining_data);


                                    unify_typoids::unify_typoids  ("1", "2", type_per_inlining_data', type_per_pkg', ["unify_pkg_with_api_type"], no_undo_log)
                                    except
                                        _ = ();

                                    fresh_meta_typevars_for_inlining_data;
                                };


                            NULL => fresh_meta_typevars_for_pkg;
                        esac;

                (unify_typoids::unify_typoids  ("1", "2", type_per_pkg', type_per_api', ["unify_pkg_with_api_type"], no_undo_log))
                except
                    _ = bug "unexpected types in unify_pkg_with_api_type";


                typevar_refs =  map  tj::typevar_of_typoid
                                     fresh_meta_typevars_for_api;


                (types, typevar_refs);
            };



        ##########################################################################
        #
        # thin_package':   Matching a package against an api.
        # 
        # WARNING: rpath is an inverse stamppath, so it has to be
        #          reversed to produce an stamppath.
        #
        fun thin_package'
                (
                  constrained_pkg
                      as
                      mld::A_PACKAGE {
                          an_api => mld::API {
                                        stamp        =>  pkg_api_stamp,
                                        api_elements =>  pkg_api_elements,
                                        ...
                                    },

                          typechecked_package
                              as
                              { stamp                  =>  pkg_stamp,
                                typerstore =>  package_typerstore,
                                ...
                              },

                          varhome      =>  constrained_pkg_varhome,
                          inlining_data =>  constrained_pkg_inline_info
                      }
                      : mld::Package,

                  constraining_api
                      as
                      mld::API {
                          stamp            =>  constraining_api_stamp,
                          closed           =>  constraining_api_is_closed,
                          contains_generic =>  constraining_api_contains_generic,
                          api_elements     =>  constraining_api_elements,
                          ...
                      }
                      : mld::Api,

                  package_name:                 sy::Symbol,

                  debruijn_depth:               di::Debruijn_Depth,
                  match_typerstore:             mld::Typerstore, 

                  rpath:                        List( sta::Stamp ),
                  inverse_path:                 ip::Inverse_Path,

                  symbolmapstack:               syx::Symbolmapstack,
                  source_code_region:           lnd::Source_Code_Region,

                  per_compile_stuff
                      as
                      { make_fresh_stamp,
                        issue_highcode_codetemp => make_var,
                        error_fn,
                        ...
                      }
                      : trj::Per_Compile_Stuff
                )
                :
                ( ds::Declaration,                      # Thinned declaration   (Becomes PACKAGE_LET.declaration in eventual deep syntax tree.)
                  mld::Package,                         # Thinned package       (Becomes PACKAGE_LET.expression  in eventual deep syntax tree.)
                  mld::Package_Expression               # Only for internal generics typechecking use: This will be used to mld::COERCED_PACKAGE original package_expression to correct api.
                )
                =>
                {   err  =  error_fn  source_code_region;
                    #
                    fun unparse_api  pps  an_api
                        =
                        upl::unparse_api pps (an_api, symbolmapstack, 2);

                    fun unparse_pkg  pps  pkg
                        =               
                        upl::unparse_package pps (pkg, syx::empty, 2);

                    fun unparse_pkg_name  pps  pkg
                        =               
                        upl::unparse_package_name pps (pkg, syx::empty);

                    title = "thin_package'/TOP - constraining_api:";

                    tyd::debug_print  show_apis  (title, unparse_api, constraining_api);

                    #
                    fun unify_typoids { type_per_api, type_per_pkg, inlining_data, name }
                        :
                        ( List( tdt::Typoid      ),
                          List( tdt::Typevar_Ref )
                        )
                        = 
                        if (tj::pkg_typoid_matches_api_typoid { type_per_api, type_per_pkg })
                            #
                            (unify_pkg_with_api_type { type_per_api, type_per_pkg, inlining_data })
                                ->
                                (types, typevar_refs);

                            (types, typevar_refs);
                        else
                            err err::ERROR 
                                "value type in package doesn't match api declaration"
                                (\\ pp
                                    =
                                    {   unparse_type::reset_unparse_type ();
                                        pp.newline();
                                        apply  pp.lit  ["  name: ", sy::name name];
                                        pp.newline();
                                        pp.lit "type_per_api:   ";
                                        unparse_type::unparse_typoid  symbolmapstack  pp  type_per_api;
                                        pp.newline();
                                        pp.lit "type_per_pkg: ";
                                        unparse_type::unparse_typoid  symbolmapstack  pp  type_per_pkg;
                                    }
                                );

                            ([],[]);
                        fi;
                    #
                    fun complain s    =   err err::ERROR s err::null_error_body;
                    fun complain' x   =   { complain x;   raise exception BAD_NAMING;};


                    # Compute mismatches between the API and package
                    # definitions of a sumtype.
                    #
                    # We are given two sorted lists of symbols:
                    #  o The sumtype constructor list per API definition,
                    #  o The sumtype constructor list per pkg definition.
                    #
                    # We return two lists:
                    #  o Data constructors appearing only the API     version,
                    #  o Data constructors appearing only the package version.
                    #  
                    # We depend on the fact that
                    # data constructors have been
                    # sorted by name:
                    #
                    fun find_unmatched_valcons (in_api, in_pkg)
                        =
                        find_unmatched (in_api, in_pkg, [], [])
                        where 
                            fun find_unmatched
                                    ( l1 as dc1 ! r1,   # "dc" == "data constructor";  "r" == "rest"
                                      l2 as dc2 ! r2,
                                      in_api_only,              # 
                                      in_pkg_only               # 
                                    )
                                    =>
                                    if (sy::eq (dc1, dc2))
                                         find_unmatched (r1, r2, in_api_only, in_pkg_only);
                                    else
                                         sy::symbol_gt (dc1, dc2)  ??   find_unmatched ( l1, r2,        in_api_only,  dc2 ! in_pkg_only )
                                                                   ::   find_unmatched ( r1, l2,  dc1 ! in_api_only,        in_pkg_only );
                                   fi;

                               find_unmatched ([], [], in_api_only, in_pkg_only)   =>   (reverse  in_api_only,       reverse  in_pkg_only     );
                               find_unmatched ([],  r, in_api_only, in_pkg_only)   =>   (reverse  in_api_only,       reverse  in_pkg_only  @ r);
                               find_unmatched ( r, [], in_api_only, in_pkg_only)   =>   (reverse  in_api_only  @ r,  reverse  in_pkg_only     );
                            end;
                        end;

                    #
                    fun check_named_type (_, tdt::ERRONEOUS_TYPE, _)
                            =>
                            {
                                                                                                                                if_debugging_say ("check_named_type(_, tdt::ERRONEOUS_TYPE, _): Just returning  Void");
                                ();
                            };

                        check_named_type (type_per_api, type_per_pkg, typerstore)
                            =>
                            {   name_per_api =   sy::name   (tj::name_of_type  type_per_api);
                                #
                                                                                                                                if_debugging_say ("check_named_type/TOP name_per_api = " + name_per_api);
                                case type_per_api
                                    #
                                    tdt::SUM_TYPE
                                        {
                                          stamp     =>  s,
                                          kind      =>  api_kind,
                                          is_eqtype =>  REF equality_property,
                                          arity,
                                          ...
                                        }
                                        =>
                                        {   fun no_sumtype ()
                                                =
                                                complain'("type " + name_per_api + " must be a sumtype");
                                                                                                                                if_debugging_say ("check_named_type/SUM_TYPE name_per_api = " + name_per_api);


                                            if (arity != tj::arity_of_type type_per_pkg)
                                                #
                                                complain' (   "type arity for "
                                                          +   name_per_api
                                                          +   " does not match specified arity"
                                                          );
                                            else
                                                # BUG: under certain circumstances (bug 1364),
                                                # a tdt::SUM_TYPE type_per_pkg should not be unwrapped.
                                                #
                                                # However, it must be unwrapped if it is a tdt::SUM_TYPE
                                                # created by instantiating a direct or indirect
                                                # sumtype replication spec (see bug 1432).
                                                #
                                                # For direct sumtype replication {\em declarations },
                                                # there is no problem because the replicated
                                                # sumtype is a SUM_TYPE.
                                                #
                                                # The unwrapping of sumtype relicants should be
                                                # performed in macro_expand, not here.          XXX BUGGO FIXME
                                                #
                                                case (api_kind, /* tj::unwrap_definition_star */ type_per_pkg)
                                                    #
                                                     ( tdt::SUMTYPE { index => api_index, family => { members, ... }, ... },
                                                       tdt::SUM_TYPE { arity => a', kind => pkg_kind, ... }
                                                     )
                                                         =>
                                                         case pkg_kind
                                                              # 
                                                              tdt::SUMTYPE { index  => pkg_index,
                                                                             family => { members => members', ... },
                                                                             ...
                                                                           }
                                                                  =>
                                                                  {   api_dcons =  (vector::get (members , api_index)).valcons;
                                                                      pkg_dcons =  (vector::get (members', pkg_index)).valcons;

                                                                      api_names = map .name  api_dcons;
                                                                      pkg_names = map .name  pkg_dcons;

                                                                      if *debugging
                                                                          apply   (\\ s =  (if_debugging_say (sy::name s)))   api_names;
                                                                          if_debugging_say "******";
                                                                          apply   (\\ s =  (if_debugging_say (sy::name s)))   pkg_names;
                                                                      fi;

                                                                      case (find_unmatched_valcons (api_names, pkg_names))
                                                                          #
                                                                          ([], []) => ();

                                                                          (in_api_only, in_pkg_only)
                                                                              =>
                                                                              complain' (
                                                                                  cat (
                                                                                      list::cat
                                                                                          [   [ "sumtype ", name_per_api, " does not match api declaration"],

                                                                                              case in_api_only
                                                                                                  [] => [];

                                                                                                  _  => [  "\n   constructors in api declaration only: ",
                                                                                                           symbols_to_string  in_api_only
                                                                                                        ];
                                                                                              esac,

                                                                                              case in_pkg_only
                                                                                                  [] => [];

                                                                                                  _  => [  "\n   constructors in package declaration only: ",
                                                                                                           symbols_to_string  in_pkg_only
                                                                                                        ];
                                                                                              esac
                                                                                          ]
                                                                                  )
                                                                              );
                                                                      esac;
                                                                  };

                                                             _   =>   no_sumtype ();
                                                         esac;


                                                    (tdt::SUMTYPE _, _) => no_sumtype ();

                                                    (tdt::FORMAL, _)
                                                         =>
                                                         if  (equality_property == tdt::e::YES
                                                              and
                                                              not (eq_types::is_equality_type  type_per_pkg)
                                                             )

                                                             complain'("type " + name_per_api + " must be an equality type");
                                                         fi;

                                                    _ => {   tyd::debug_print
                                                                  debugging
                                                                  (   "type_per_api: ",
                                                                      unparse_type::unparse_type  symbolmapstack,
                                                                      type_per_api
                                                                  );

                                                              tyd::debug_print
                                                                  debugging
                                                                  (   "type_per_pkg: ",
                                                                      unparse_type::unparse_type  symbolmapstack,
                                                                      type_per_pkg
                                                                  );

                                                              bug "check_type_naming 1";
                                                          };
                                                  esac;

                                            fi;
                                        };

                                   tdt::NAMED_TYPE { typescheme => tdt::TYPESCHEME { body, arity }, strict, stamp, namepath }
                                       => 
                                       {
                                                                                                                                if_debugging_say ("check_named_type/tdt::SUM_TYPE/TOP name_per_api = " + name_per_api + "   src/lib/compiler/front/typer/modules/api-match-g.pkg");
                                           typescheme
                                               =
                                               tdt::TYPESCHEME
                                                 { body  => mj::translate_typoid  typerstore  body,
                                                   arity
                                                 };

                                                                                                                                if_debugging_say ("check_named_type/tdt::SUM_TYPE/AAA name_per_api = " + name_per_api + "   src/lib/compiler/front/typer/modules/api-match-g.pkg");
                                           type_per_api'
                                               =
                                               tdt::NAMED_TYPE
                                                 {
                                                   typescheme,          # The only part we change.
                                                   strict,
                                                   stamp,
                                                   namepath
                                                 };


                                                                                                                                if_debugging_say ("check_named_type/tdt::SUM_TYPE/BBB name_per_api = " + name_per_api + "   src/lib/compiler/front/typer/modules/api-match-g.pkg");
                                           if (not (tj::type_equality (type_per_api', type_per_pkg)))
                                                #
                                                tyd::debug_print
                                                    debugging
                                                    (   "type_per_api': ",
                                                        unparse_type::unparse_type  symbolmapstack,
                                                        type_per_api'
                                                    );

                                                tyd::debug_print
                                                    debugging
                                                    (   "type_per_pkg: ",
                                                        unparse_type::unparse_type  symbolmapstack,
                                                        type_per_pkg
                                                    );

                                                complain'
                                                    (   "type "
                                                    +   name_per_api
                                                    +   " does not match api declaration"
                                                    );
                                           fi;
                                       };

                                    tdt::ERRONEOUS_TYPE =>   raise exception BAD_NAMING;
                                    _                 =>   bug "check_named_type 2";

                                esac;
                            };
                    end;                                                        # fun check_named_type

                    stipulate

                        # Two support functions local to check_sharing():
                        #
                        fun find_package_via_symbol_path
                            (
                              elements,
                              typerstore
                            )
                            (syp::SYMBOL_PATH  spath)
                            :
                            ( mld::Api,
                              mld::Typerstore_Entry
                            )
                            =
                            loop (spath, elements, typerstore)
                            where 
                                fun loop ( [symbol], elements, typerstore)
                                        =>
                                       case (mj::get_api_element (elements, symbol))

                                           mld::PACKAGE_IN_API { module_stamp, an_api, ... }
                                               =>
                                               {   if_debugging_say ("@@@find_package_via_symbol_path.1: " + sy::name symbol + ", " + ep::module_stamp_to_string  module_stamp);

                                                   (an_api, tro::find_entry_by_module_stamp (typerstore, module_stamp));
                                               };

                                           _ => bug "loop_package 1b";
                                       esac
                                       except
                                           mj::UNBOUND _ =  bug "find_package_via_symbol_path 1c";


                                    loop (symbol ! rest, elements, typerstore)
                                        =>
                                        case (mj::get_api_element (elements, symbol))
                                            #
                                            mld::PACKAGE_IN_API { an_api => mld::API { api_elements, ... }, module_stamp, ... }
                                                =>
                                                case (tro::find_entry_by_module_stamp (typerstore, module_stamp))
                                                    #
                                                    mld::PACKAGE_ENTRY { typerstore, ... }
                                                        =>
                                                        {   if_debugging_say ( "@@@find_package_via_symbol_path.2: "
                                                                           + sy::name symbol
                                                                           + ", "
                                                                           + ep::module_stamp_to_string module_stamp
                                                                           );

                                                            loop (rest, api_elements, typerstore);
                                                        };

                                                    mld::ERRONEOUS_ENTRY
                                                        =>
                                                        (mld::ERRONEOUS_API, mld::ERRONEOUS_ENTRY);

                                                     _   => bug "find_package_via_symbol_path 2a";
                                                esac;

                                            _   => bug "find_package_via_symbol_path 2b";
                                        esac
                                        except
                                            mj::UNBOUND _ =  bug "find_package_via_symbol_path 2c";


                                   loop _ => bug "find_package_via_symbol_path 3";

                                end;                    # fun loop
                            end;                        # where


                        #
                        fun find_type_via_symbol_path (elements, typerstore) (syp::SYMBOL_PATH spath)
                            :
                            tdt::Type
                            =
                            loop (spath, elements, typerstore)
                            where
                                fun loop ([symbol], elements, typerstore)
                                       =>
                                       case (mj::get_api_element (elements, symbol))
                                           #
                                           mld::TYPE_IN_API { module_stamp, ... }
                                               =>
                                               case (tro::find_entry_by_module_stamp (typerstore, module_stamp))
                                                   #
                                                   mld::TYPE_ENTRY  type =>   type;
                                                   mld::ERRONEOUS_ENTRY  =>   tdt::ERRONEOUS_TYPE;
                                                   _                     =>   bug "find_type_via_symbol_path 1a";
                                               esac;

                                            _ => bug "find_type_via_symbol_path 1b";
                                        esac
                                        except
                                            mj::UNBOUND _ =  bug "find_type_via_symbol_path 1c";


                                    loop (symbol ! rest, elements, typerstore)
                                        =>
                                        case (mj::get_api_element (elements, symbol))

                                             mld::PACKAGE_IN_API { an_api => mld::API { api_elements, ... }, module_stamp, ... }
                                                 =>
                                                 case (tro::find_entry_by_module_stamp (typerstore, module_stamp))
                                                     #
                                                     mld::PACKAGE_ENTRY { typerstore, ... }
                                                          =>
                                                          loop (rest, api_elements, typerstore);

                                                     mld::ERRONEOUS_ENTRY =>   tdt::ERRONEOUS_TYPE;
                                                     _                    =>   bug "find_type_via_symbol_path 2a";
                                                 esac;

                                            _ => bug "find_type_via_symbol_path 2b";
                                        esac
                                        except
                                            mj::UNBOUND _
                                                =
                                                bug ("find_type_via_symbol_path 2c:" + symbol::name symbol +  syp::to_string (syp::SYMBOL_PATH spath));


                                   loop _ => bug "find_type_via_symbol_path 3";
                                end;
                            end;

                    herein

                        # Check whether all sharing constraints are satisfied:
                        #
                        fun check_sharing ( an_api as mld::ERRONEOUS_API, typerstore)
                                =>
                                ();                   #  Don't do anything if an error has occurred, resulting in an mld::ERRONEOUS_API 

                            check_sharing (an_api as mld::API { api_elements, type_sharing, package_sharing, ... }, typerstore)
                                =>
                                {   fun errmsg sp x
                                        =
                                        syp::to_string x + " != " + syp::to_string sp;
                                    #
                                    fun eq_type (_, tdt::ERRONEOUS_TYPE) => TRUE;
                                        eq_type (tdt::ERRONEOUS_TYPE, _) => TRUE;

                                        eq_type (type1, type2)
                                            =>
                                            tj::type_equality (type1, type2);
                                    end;

                                    find_package_via_symbol_path
                                        =
                                        find_package_via_symbol_path
                                          ( api_elements,
                                            typerstore
                                          );

                                    #
                                    fun common_elements
                                          (
                                            mld::API  api1,
                                            mld::API  api2
                                          )
                                            =>
                                            {   elements1 =  api1.api_elements;
                                                elements2 =  api2.api_elements;
                                                #
                                                fun elem_gt ((s1, _), (s2, _))
                                                    =
                                                    sy::symbol_gt (s1, s2);

                                                elements1 =  lms::sort_list  elem_gt  elements1;
                                                elements2 =  lms::sort_list  elem_gt  elements2;

                                                intersect (elements1, elements2)
                                                where
                                                    fun intersect (e1 as ((s1, spec1) ! rest1),
                                                                   e2 as ((s2, spec2) ! rest2))
                                                            =>
                                                            if   (sy::eq (s1, s2))

                                                                 (s1, spec1, spec2)   !   intersect (rest1, rest2);
                                                            else 
                                                                 if   (sy::symbol_gt (s1, s2))   intersect (e1, rest2);
                                                                 else                           intersect (rest1, e2);
                                                                 fi;
                                                            fi;

                                                        intersect(_, _)
                                                            =>
                                                            NIL;

                                                    end;                        # fun intersect
                                                end;                            # where
                                            };

                                        common_elements _
                                            =>
                                            bug "common_elements";
                                    end;                                        # fun common_elements

                                    # Apply 'test' to all possible
                                    # pairs of values from given
                                    # list -- O(N**2) tests for
                                    # length-N list:
                                    #
                                    fun apply_to_all_pairs  test  NIL
                                            =>
                                            ();

                                        apply_to_all_pairs  test  (a ! r)
                                            =>
                                            {   apply  (\\ x = test (a, x))  r;
                                                apply_to_all_pairs test r;
                                            };
                                    end;
                                    #
                                    fun compare_packages
                                            ( (p1, (an_api1, ent1)),
                                              (p2, (an_api2, ent2))
                                            )
                                        = 
                                        case (ent1, ent2)

                                             ( mld::PACKAGE_ENTRY { stamp => s1, typerstore => dict1, ... },
                                               mld::PACKAGE_ENTRY { stamp => s2, typerstore => dict2, ... }
                                             )
                                                 =>
                                                 if (sta::same_stamp (s1, s2))

                                                      ();   #  shortcut! 
                                                 else
                                                      if   (mj::apis_equal (an_api1, an_api2))

                                                           if_debugging_say "@@@compare_packages: an_api1 == an_api2";

                                                           my { api_elements, ... }
                                                               =
                                                               case an_api1    mld::API api_record =>  api_record;
                                                                               _                   =>  bug "compare_packages: mld::API";
                                                               esac;

                                                           for'  api_elements  compare
                                                           where 
                                                               fun compare (symbol, mld::TYPE_IN_API { module_stamp, ... } )
                                                                       => 
                                                                       {   type1   =   unwrap_typecon_entry (tro::find_entry_by_module_stamp (dict1, module_stamp));
                                                                           type2   =   unwrap_typecon_entry (tro::find_entry_by_module_stamp (dict2, module_stamp));

                                                                           if (not (eq_type (type1, type2)))

                                                                                complain (
                                                                                    cat
                                                                                        [   "implied type sharing violation: ",
                                                                                            errmsg
                                                                                               (syp::extend (p1, symbol))
                                                                                               (syp::extend (p2, symbol))
                                                                                        ]
                                                                                );
                                                                           fi;
                                                                       };

                                                                   compare (symbol, mld::PACKAGE_IN_API { module_stamp, an_api, ... } )
                                                                       => 
                                                                       {   ent1' = tro::find_entry_by_module_stamp (dict1, module_stamp);
                                                                           ent2' = tro::find_entry_by_module_stamp (dict2, module_stamp);

                                                                           compare_packages (
                                                                               (syp::extend (p1, symbol),   (an_api, ent1')),
                                                                               (syp::extend (p2, symbol),   (an_api, ent2'))
                                                                           );
                                                                       };

                                                                   compare _   => ();

                                                                end;                    # fun compare
                                                            end;                        # where


                                                      else
                                                           if_debugging_say "@@@compare_packages: an_api1 != an_api2";

                                                           common_api_elements
                                                               =
                                                               common_elements (an_api1, an_api2);

                                                           for' common_api_elements

                                                                \\ ( symbol,
                                                                     mld::TYPE_IN_API { module_stamp => v1, ... },
                                                                     mld::TYPE_IN_API { module_stamp => v2, ... }
                                                                   )
                                                                       =>
                                                                       {   type1 = unwrap_typecon_entry (tro::find_entry_by_module_stamp (dict1, v1));
                                                                           type2 = unwrap_typecon_entry (tro::find_entry_by_module_stamp (dict2, v2));

                                                                           if (not (eq_type (type1, type2)))
                                                                               #
                                                                               complain( cat [ "type sharing violation: ",
                                                                                               errmsg (syp::extend (p1, symbol))
                                                                                               (syp::extend (p2, symbol))
                                                                                             ]
                                                                                       );
                                                                           fi;
                                                                       };

                                                                   ( symbol,
                                                                     mld::PACKAGE_IN_API { module_stamp=>v1, an_api => an_api1', ... },
                                                                     mld::PACKAGE_IN_API { module_stamp=>v2, an_api => an_api2', ... }
                                                                   )
                                                                       =>
                                                                       {   str1 = tro::find_entry_by_module_stamp (dict1, v1);
                                                                           str2 = tro::find_entry_by_module_stamp (dict2, v2);

                                                                           compare_packages ( (syp::extend (p1, symbol), (an_api1', str1)),
                                                                                              (syp::extend (p2, symbol), (an_api2', str2))
                                                                                            );
                                                                       };


                                                                   _   => ();

                                                                end;            # fn
                                                      fi;
                                                 fi;

                                            (mld::ERRONEOUS_ENTRY, _) => ();  #  error upstream 
                                            (_, mld::ERRONEOUS_ENTRY) => ();  #  error upstream 
                                             _                   => bug "compare_packages";

                                        esac;
                                    #
                                    fun check_package  paths
                                        =
                                        {   pathstrs
                                                =
                                                map  (\\ p =  (p, find_package_via_symbol_path p))
                                                     paths;

                                            apply_to_all_pairs  compare_packages  pathstrs;
                                        };
                                    #
                                    fun check_type' (first_path, rest)
                                        =
                                        {   find_type_via_symbol_path
                                                =
                                                find_type_via_symbol_path
                                                  (
                                                    api_elements,
                                                    typerstore
                                                  );

                                            err_msg =   errmsg first_path;

                                            first   =   find_type_via_symbol_path
                                                            first_path;

                                            apply  check_path  rest
                                            where
                                                fun check_path p
                                                    = 
                                                    if (not (eq_type (first, find_type_via_symbol_path p)))
                                                        #
                                                        complain (cat [ "type sharing violation: ", err_msg p ] );
                                                    fi;
                                            end;
                                        };
                                    #
                                    fun check_type (sp ! rest) =>   check_type' (sp, rest);
                                        check_type _           =>   bug "check_sharing: check_type";
                                    end;


                                    apply  check_package          package_sharing;
                                    apply  check_type    type_sharing;
                                };
                        end;                    # fun check_sharing 
                    end;                        # stipulate

                    # Matching: Go through the `elements' of the specified api,
                    # and  construct a corresponding typechecked_package
                    # from typerstore found in the given package.
                    #
                    # The package's typerstore entries are found
                    # by using the stamppath in each of the given package api's
                    # elements to access the given package's typechecked_package
                    # = stored typerstore.
                    #
                    # Subpackages are processed recursively.
                    #
                    # Build the formal typechecked_package in parallel.
                    #
                    # Finally check sharing constraints.


                    # fun match_all_api_elements:
                    #     ( List( sy::Symbol, Api_Element ),
                    #       Typerstore,
                    #       List( Module_Declaration ),
                    #       List( ds::Declaration ),
                    #       List( sxe::Symbolmapstack_Entry )
                    #     )
                    #     ->
                    #     ( List( ds::Declaration ),
                    #       List( sxe::Symbolmapstack_Entry ),
                    #       Typerstore,
                    #       List( Module_Declaration)
                    #     )  
                    #
                    # Given the elements and the typerstore
                    # of a constrained package and a constraining api,
                    # extend the typechecked_package (Typerstore)
                    # with the typechecked_package specified by the spec,
                    # extend the list of coercions (typechecked_package declarations)
                    # with a declaration which will evaluate to the
                    # new typechecked_package, and extend the thinning.
                    #
                    # We assume that if a match error occurs
                    # then the resulting thinning and the
                    # list of module_declarations
                    # will never be used -- they will not be
                    # well-formed in case of errors. 

                    stipulate

                        # A private support function for
                        #     fun match_all_api_elements:
                        #
                        fun match_def_package  args
                            =
                            case args
                                ( api_elements,
                                  mld::A_PACKAGE { an_api => api_d, typechecked_package => typechecked_package_d, ... },                # Package from constraining api.
                                  mld::A_PACKAGE { an_api => api_m, typechecked_package => typechecked_package_m, ... }         # Package from constrained package.
                                )
                                    =>
                                    {   stamp_d =  typechecked_package_d.stamp;
                                        stamp_m =  typechecked_package_m.stamp;

                                        if (sta::same_stamp (stamp_d, stamp_m))         #  eq_origin 
                                             TRUE;
                                        else
                                             match_def_package'
                                                 (
                                                   api_elements,
                                                   api_d,  typechecked_package_d,
                                                   api_m,  typechecked_package_m
                                                 );
                                        fi;
                                    };

                                _   => bug "match_def_package (2)";
                            esac
                            where
                                # Private support function for match_def_package():
                                #
                                fun match_def_package'
                                    (
                                      api_elements,
                                      api_d, typechecked_package_d,
                                      api_m, typechecked_package_m
                                    )
                                    =
                                    {   # Function to drop from api element list all elements
                                        # except for mld::TYPE_IN_API and mld::PACKAGE_IN_API:
                                        #
                                        drop_vals
                                            =
                                            list::filter
                                                \\ (s, (mld::TYPE_IN_API _ | mld::PACKAGE_IN_API _ )) =>  TRUE;
                                                   _                                                 =>  FALSE;
                                                end ;


                                        nonvalue_api_elements
                                           =
                                           drop_vals  api_elements;

                                        #
                                        fun elem_gt ((s1, _), (s2, _))
                                            =
                                            sy::symbol_gt (s1, s2);

                                        # Get the list of elements from an API.
                                        # Each element is a (name, value) pair
                                        # where the name is a symbol:
                                        #
                                        fun get_elements (mld::API { api_elements, ... }) =>  api_elements;
                                            get_elements _                                =>  bug "match_def_package': API (1)";
                                        end;

                                        # The api_d (constraining) api elements will be a list of (symbol, type_d) pairs.
                                        # The api_m (constrained ) api elements will be a list of (symbol, type_m) pairs.
                                        #
                                        # From the pairs with matching symbols, create a list of triples
                                        #     (symbol, type_d, type_m)
                                        #
                                        common_dm_api_elements
                                            =
                                            if (mj::apis_equal (api_d, api_m))
                                                #
                                                api_elements
                                                    =
                                                    lms::sort_list
                                                        elem_gt
                                                        (drop_vals  (get_elements  api_d));

                                                map (\\ (s, spec) =  (s, spec, spec))
                                                    api_elements;

                                            else

                                                elements_d =   lms::sort_list  elem_gt  (drop_vals  (get_elements  api_d));
                                                elements_m =   lms::sort_list  elem_gt  (drop_vals  (get_elements  api_m));

                                                intersect (elements_d, elements_m)
                                                where
                                                    fun intersect (list1 as ((symbol1, spec1) ! rest1),
                                                                   list2 as ((symbol2, spec2) ! rest2)
                                                                  )
                                                            =>
                                                            if   (sy::eq (symbol1, symbol2))

                                                                 (symbol1, spec1, spec2) ! intersect (rest1, rest2);
                                                            else
                                                                 (sy::symbol_gt (symbol1, symbol2))
                                                                     ?? intersect (list1, rest2)
                                                                     :: intersect (rest1, list2);
                                                            fi;

                                                        intersect(_, _) => NIL;

                                                    end;                        # fun intersect
                                                end;                            # where
                                            fi;

                                        # Here we reduce the above list of triples to
                                        # those it has in common with nonvalue_api_elements,
                                        # and add in the type information from the latter,
                                        # yielding a list of quadruples
                                        #     (symbol, type_a, type_d, type_m)
                                        #
                                        common_api_elements
                                            =
                                            intersect' (nonvalue_api_elements, common_dm_api_elements)
                                            where
                                                fun intersect' (  elements1 as ((symbol1, x)    ! rest1),
                                                                  elements2 as ((symbol2, y, z) ! rest2)
                                                               )
                                                        =>
                                                        if   (sy::eq (symbol1, symbol2))

                                                             (symbol1, x, y, z)   !   intersect' (rest1, rest2);
                                                        else
                                                             sy::symbol_gt (symbol1, symbol2)
                                                                 ?? intersect' (elements1, rest2)       #  Discard symbol2 
                                                                 :: intersect' (rest1, elements2);      #  Discard symbol1 
                                                        fi;

                                                    intersect' (_, _)
                                                        =>
                                                        NIL;
                                                end;                    # fun intersect'
                                            end;                        # where



                                        loop  common_api_elements
                                        where
                                            fun loop NIL
                                                    =>
                                                    TRUE;

                                                loop ((symbol, api_element, spec_d, spec_m) ! rest)
                                                    =>
                                                    case api_element
                                                        #
                                                        mld::TYPE_IN_API _
                                                            =>
                                                            {   fun unwrap_typecon (mld::TYPE_IN_API x) =>  x;
                                                                    unwrap_typecon _                           =>  bug "thin_package': unTypespec";
                                                                end;

                                                                modstamp_d =  (unwrap_typecon spec_d).module_stamp;
                                                                modstamp_m =  (unwrap_typecon spec_m).module_stamp;

                                                                dictionary_d =  typechecked_package_d.typerstore;
                                                                dictionary_m =  typechecked_package_m.typerstore;

                                                                tyc_d = unwrap_typecon_entry (tro::find_entry_by_module_stamp (dictionary_d, modstamp_d));
                                                                tyc_m = unwrap_typecon_entry (tro::find_entry_by_module_stamp (dictionary_m, modstamp_m));

                                                                tj::type_equality (tyc_d, tyc_m)
                                                                and
                                                                loop rest;                      # Added recursive call because a 'loop' fn which didn't loop seemed odd.        -- 2009-07-18 CrT
                                                            };

                                                        mld::PACKAGE_IN_API { an_api => mld::API { api_elements, ... }, ... }
                                                            =>
                                                            {   fun unwrap_pkg_spec (mld::PACKAGE_IN_API x) =>  x;
                                                                    unwrap_pkg_spec _                  =>  bug "thin_package': unwrap_pkg_spec";
                                                                end;

                                                                my { module_stamp => modstamp_d,  an_api => api_d',  ... } =  unwrap_pkg_spec spec_d;
                                                                my { module_stamp => modstamp_m,  an_api => api_m',  ... } =  unwrap_pkg_spec spec_m;

                                                                dictionary_d =  typechecked_package_d.typerstore;
                                                                dictionary_m =  typechecked_package_m.typerstore;

                                                                fun unwrap_pkg_entry (mld::PACKAGE_ENTRY x) =>  x;
                                                                    unwrap_pkg_entry _                 =>  bug "thin_package': unwrap_pkg_entry";
                                                                end;

                                                                typechecked_package_d' = unwrap_pkg_entry (tro::find_entry_by_module_stamp (dictionary_d, modstamp_d));
                                                                typechecked_package_m' = unwrap_pkg_entry (tro::find_entry_by_module_stamp (dictionary_m, modstamp_m));

                                                                # Call ourself recursively
                                                                # to process subpackage:
                                                                #
                                                                match_def_package'
                                                                  (
                                                                    api_elements,
                                                                    api_d', typechecked_package_d',
                                                                    api_m', typechecked_package_m'
                                                                  )
                                                                and
                                                                loop rest;                      # Added recursive call because a 'loop' fn which didn't loop seemed odd.        -- 2009-07-18 CrT
                                                            };

                                                    _   => bug "thin_package'";

                                                esac;
                                            end;                # fun loop
                                        end;                    # where
                                    };                          # fun match_def_package'
                            end;                                # where

                    herein      
                        #
                        fun match_all_api_elements
                                ( [],                           # Input list exhausted, time to construct final result.
                                  typerstore,
                                  module_declarations,
                                  abstract_declarations,
                                  symbolmapstack_entries,
                                  match_succeeded
                                )
                                =>
                                ( reverse  abstract_declarations,
                                  reverse  symbolmapstack_entries,
                                  typerstore,
                                  reverse  module_declarations,
                                  match_succeeded
                                );

                            match_all_api_elements
                                ( (api_element_symbol, api_element) ! remaining_api_elements,   # Input list, starts as constraining_api_elements.
                                  typerstore,                                                   # Dictionary accumulating seen generics, also mld::TYPE_ENTRY, also thinned_package from  thin_package'.
                                  module_declarations,                                          # List accumulating mld::Module_Declaration stuff: mld::TYPE_DECLARATION, PACKAGE_DECLARATION, GENERIC_DECLARATION (...?) 
                                  abstract_declarations,                                        # List accumulating deep syntax: ds::VALUE_DECLARATIONS[ PLAIN_VARIABLE | NAMED_VALUE ]
                                  symbolmapstack_entries,                                       # List accumulating symbol table entries: sxe::NAMED_CONSTRUCTOR, NAMED_VARRIABLE, NAMED_PACKAGE, NAMED_GENERIC.
                                  match_succeeded                                               # Starts TRUE, set FALSE at first api/pkg mismatch detected.
                                )
                                =>
                                {   if_debugging_say "match_all_api_elements/TOP";

                                    # Issue an error message,
                                    # remember that the api match failed,
                                    # process rest of api elements anyhow:
                                    #
                                    fun complain_and_loop (kind_op: Null_Or( String ))
                                        =
                                        {   typerstore'
                                                = 
                                                case (mj::get_api_element_variable  api_element)
                                                    #
                                                    THE v => tro::set (typerstore, v, mld::ERRONEOUS_ENTRY);
                                                    NULL  => typerstore;
                                                esac;

                                            # Synthesize a new error naming
                                            # to remove improper error
                                            # messages on inline_info (ZHONG)

                                            symbolmapstack_entries'
                                                = 
                                                case api_element
                                                    #
                                                    mld::TYPE_IN_API _                             =>  symbolmapstack_entries;
                                                    #
                                                    mld::VALCON_IN_API { slot=>NULL, ... } =>  symbolmapstack_entries;

                                                    _ => sxe::NAMED_CONSTRUCTOR variables_and_constructors::bogus_exception ! symbolmapstack_entries;
                                                esac;

                                            case kind_op
                                                #
                                                NULL     =>   ();
                                                THE kind =>   {   complain("Sealed package lacks api-required element: " + kind + " " + sy::name api_element_symbol);
                                                                  # Added 2011-05-30 CrT because above alone is often totally mysterious
                                                                  # in the presence of large nested generic-package invocations:
#                                                                 tyd::debug_print (REF TRUE)  ("Constrained pkg name:", unparse_pkg_name, constrained_pkg );   # Unhelpful; prints "?<empty spath>", or "?back_patch" or such.
                                                                  tyd::debug_print (REF TRUE)  ("Constrained  pkg:",     unparse_pkg,      constrained_pkg );
                                                                  tyd::debug_print (REF TRUE)  ("Constraining api:",     unparse_api,      constraining_api);
                                                              };        
                                            esac;

                                            # Match has failed, but process rest of API
                                            # to maybe generate additional useful diagnostics
                                            # for user:
                                            #   
                                            match_all_api_elements
                                              (
                                                remaining_api_elements,
                                                typerstore',
                                                module_declarations,
                                                abstract_declarations,
                                                symbolmapstack_entries',
                                                FALSE                           # Remember that API match failed.
                                              );
                                        };
                                    #
                                    fun type_in_matched (kind, type)
                                         = 
                                         (mj::translate_typoid  typerstore  type) 
                                         except
                                             tro::UNBOUND
                                                 =
                                                 {   tyd::debug_print  debugging  (kind, unparse_type::unparse_typoid  symbolmapstack, type);
                                                     raise exception tro::UNBOUND;
                                                 };
                                    #
                                    fun type_in_original (kind, type)
                                         = 
                                         (mj::translate_typoid  package_typerstore  type) 
                                         except
                                             tro::UNBOUND
                                                 =
                                                 {   tyd::debug_print  debugging  (kind, unparse_type::unparse_typoid  symbolmapstack, type);
                                                     raise exception tro::UNBOUND;
                                                 };


                                    case api_element
                                        #
                                        mld::TYPE_IN_API { type => type_per_api, module_stamp, is_a_replica, scope }
                                            =>
                                            {   if_debugging_say ( string::cat [ "match_all_api_elements mld::TYPE_IN_API/TOP: ",
                                                                                 sy::name api_element_symbol, ", ",
                                                                                 sta::to_string  module_stamp ] );

                                                my (type_per_pkg, pkg_typechecked_package_variable)
                                                    =
                                                    mj::get_type (pkg_api_elements, package_typerstore, api_element_symbol)
                                                    except
                                                        tro::UNBOUND 
                                                           =
                                                           {   tyd::debug_print
                                                                   debugging
                                                                   (   "package_typerstore: ", 
                                                                       (\\ pps = \\ ee = unparse_package_language::unparse_typerstore pps (ee, symbolmapstack, 6)),
                                                                       package_typerstore
                                                                   );
                                                               raise exception tro::UNBOUND;
                                                           };

                                                if_debugging_say ("--match_all_api_elements mld::TYPE_IN_API - pkg_typecheck_package_variable: " +
                                                                  sta::to_string  pkg_typechecked_package_variable);

                                                # ** DAVE: please check the following ! XXX BUGGO FIXME **

                                                tyc_module_expression
                                                    = 
                                                    case rpath
                                                        #
                                                        [] =>  mld::CONSTANT_TYPE type_per_pkg;
                                                        _  =>  mld::TYPEVAR_TYPE (reverse (pkg_typechecked_package_variable ! rpath));
                                                    esac;

                                                if_debugging_say "--match_all_api_elements mld::TYPE_IN_API calling check_named_type";

                                                check_named_type (type_per_api, type_per_pkg, typerstore);

                                                if_debugging_say "--match_all_api_elements mld::TYPE_IN_API calling tro::set";

                                                typerstore'
                                                    =
                                                    tro::set
                                                      (
                                                        typerstore,
                                                        module_stamp,
                                                        mld::TYPE_ENTRY type_per_pkg
                                                      );

                                                module_declarations'
                                                    =
                                                    mld::TYPE_DECLARATION (

                                                        module_stamp,
                                                        tyc_module_expression
                                                    )
                                                    !
                                                    module_declarations;

                                                if_debugging_say "match_all_api_elements mld::TYPE_IN_API/BOT  check_named_type";

                                                match_all_api_elements (
                                                    #
                                                    remaining_api_elements,
                                                    typerstore',
                                                    module_declarations',
                                                    abstract_declarations,
                                                    symbolmapstack_entries,
                                                    match_succeeded
                                                );
                                            }
                                            except
                                                mj::UNBOUND symbol
                                                    =>
                                                    complain_and_loop (THE "type");

                                                BAD_NAMING
                                                    =>
                                                    complain_and_loop NULL;

                                                tro::UNBOUND
                                                    =>
                                                    {   if_debugging_say ("match_all_api_elements (mld::TYPE_IN_API) tro::UNBOUND raised for: " + sy::name  api_element_symbol);
                                                        raise exception tro::UNBOUND;
                                                    };
                                            end; 


                                        mld::PACKAGE_IN_API
                                            { an_api => this_spec_api  as  mld::API api_record,
                                              module_stamp,
                                              definition,
                                              ...
                                            }
                                            =>
                                            {   this_elements =  api_record.api_elements;

                                                if_debugging_say (
                                                    string::cat [
                                                        "--match_all_api_elements mld::PACKAGE_IN_API: ",
                                                        sy::name  api_element_symbol,
                                                        ", ",
                                                         sta::to_string module_stamp
                                                    ]
                                                );

                                                my (pkg_package, pkg_package_module_stamp)
                                                    = 
                                                    mj::get_package
                                                      (
                                                        pkg_api_elements,
                                                        package_typerstore,
                                                        api_element_symbol,
                                                        constrained_pkg_varhome,
                                                        constrained_pkg_inline_info
                                                      );

                                                #  Verify spec definition, if any 

                                                # match_def_package now does the proper deep, component-wise
                                                # comparison of api_package and pkg_package when their stamps
                                                # don't agree, but the error message printed
                                                # when definition spec is not matched leaves something
                                                # to be desired XXX BUGGO FIXME
                                                #
                                                case definition
                                                    #
                                                    NULL => ();

                                                    THE (package_definition, _)
                                                        =>
                                                        {    api_package
                                                                 =
                                                                 mj::package_definition_to_package (
                                                                     package_definition,
                                                                     typerstore
                                                                 );

                                                             if (not (match_def_package (this_elements, api_package, pkg_package)))

                                                                 case package_definition

                                                                      mld::VARIABLE_PACKAGE_DEFINITION (an_api, stamppath)
                                                                          =>
                                                                          if_debugging_say (   "spec def VAR: "
                                                                                         +   ep::stamppath_to_string  stamppath
                                                                                         +   "\n"
                                                                                         );

                                                                      mld::CONSTANT_PACKAGE_DEFINITION _
                                                                          =>
                                                                          if_debugging_say ("spec def CONST\n");
                                                                  esac;

                                                                  if_debugging_show_package("api_package: ", api_package);
                                                                  if_debugging_show_package("pkg_package: ", pkg_package);

                                                                  complain (   "package def spec for "
                                                                           +   sy::name  api_element_symbol
                                                                           +   " not matched"
                                                                           );

                                                             fi;
                                                         };
                                                esac;

                                                rpath'         =   pkg_package_module_stamp ! rpath;
                                                inverse_path'  =   ip::extend (inverse_path,  api_element_symbol);

                                                # Call ourself recursively
                                                # to process subpackage:
                                                #
                                                my  ( thinned_declaration,
                                                      thinned_package,
                                                      package_expression
                                                    )
                                                    = 
                                                    thin_package' (
                                                        pkg_package,
                                                        this_spec_api,
                                                        api_element_symbol,
                                                        debruijn_depth,
                                                        typerstore,
                                                        rpath',
                                                        inverse_path',
                                                        symbolmapstack,
                                                        source_code_region,
                                                        per_compile_stuff
                                                    );

                                                typerstore'
                                                    = 
                                                    {   typechecked_package
                                                            = 
                                                            case thinned_package
                                                                mld::A_PACKAGE { typechecked_package, ... } =>  typechecked_package;
                                                                _                                         =>  mld::bogus_typechecked_package;
                                                            esac;

                                                        tro::set (typerstore,  module_stamp,  mld::PACKAGE_ENTRY typechecked_package);
                                                    };

                                                module_declarations'
                                                    =
                                                    mld::PACKAGE_DECLARATION  (module_stamp,  package_expression,  api_element_symbol)
                                                    !
                                                    module_declarations ;

                                                abstract_declarations'
                                                     =
                                                     thinned_declaration ! abstract_declarations;

                                                symbolmapstack_entries'
                                                    =
                                                    (sxe::NAMED_PACKAGE thinned_package)
                                                    !
                                                    symbolmapstack_entries;


                                                match_all_api_elements
                                                  (
                                                    remaining_api_elements,
                                                    typerstore',
                                                    module_declarations',
                                                    abstract_declarations',
                                                    symbolmapstack_entries',
                                                    match_succeeded
                                                  );
                                            }
                                            except mj::UNBOUND symbol
                                                   =
                                                   complain_and_loop (THE "package");


                                        mld::GENERIC_IN_API { a_generic_api => spec_api, module_stamp, ... }
                                            => 
                                            (   {   if_debugging_say (
                                                        string::cat [
                                                            "--match_all_api_elements mld::GENERIC_IN_API: ",
                                                            sy::name  api_element_symbol,
                                                            ", ",
                                                            sta::to_string module_stamp
                                                        ]
                                                    );

                                                    my (pkg_g, generic_module_stamp)
                                                        = 
                                                        mj::get_generic (

                                                            pkg_api_elements,
                                                            package_typerstore,
                                                            api_element_symbol,
                                                            constrained_pkg_varhome,
                                                            constrained_pkg_inline_info
                                                        );

                                                    expression'
                                                        =
                                                        mld::VARIABLE_GENERIC (reverse (generic_module_stamp ! rpath));

                                                    inverse_path'
                                                        =
                                                        ip::extend (inverse_path,  api_element_symbol);

                                                    my (thinned_declaration, thinned_g, generic_expression)
                                                        = 
                                                        match_generic1
                                                          (
                                                            spec_api,
                                                            pkg_g,
                                                            api_element_symbol,
                                                            debruijn_depth,
                                                            typerstore,
                                                            expression', 
                                                            inverse_path',
                                                            symbolmapstack,
                                                            source_code_region,
                                                            per_compile_stuff
                                                          );

                                                    typerstore'
                                                        = 
                                                        {   typechecked_generic
                                                                = 
                                                                case thinned_g
                                                                    mld::GENERIC { typechecked_generic, ... } => typechecked_generic;
                                                                    _                                       => mld::bogus_typechecked_generic;
                                                                esac;

                                                            tro::set (

                                                                typerstore,
                                                                module_stamp,
                                                                mld::GENERIC_ENTRY typechecked_generic
                                                            );
                                                        };

                                                    module_declarations'
                                                        =
                                                        mld::GENERIC_DECLARATION (module_stamp, generic_expression)
                                                        !
                                                        module_declarations;

                                                    abstract_declarations'
                                                        =
                                                        thinned_declaration ! abstract_declarations;

                                                    symbolmapstack_entries'
                                                        =
                                                        (sxe::NAMED_GENERIC thinned_g) ! symbolmapstack_entries;

                                                    match_all_api_elements
                                                      (
                                                        remaining_api_elements,
                                                        typerstore',
                                                        module_declarations',
                                                        abstract_declarations',
                                                        symbolmapstack_entries',
                                                        match_succeeded
                                                     );
                                                }
                                                except mj::UNBOUND symbol
                                                       =
                                                       complain_and_loop (THE "generic package")
                                            );

                                        mld::VALUE_IN_API { typoid => type_per_api, ... }
                                            => 
                                            case (mj::get_api_element (pkg_api_elements, api_element_symbol))
                                                #
                                                 mld::VALUE_IN_API { typoid => type_per_pkg, slot => slot_per_pkg }
                                                     =>
                                                     {   type_per_api = type_in_matched  ("@@@type_per_api (my/val)", type_per_api);
                                                         type_per_pkg = type_in_original ("@@@type_per_pkg (my/val)", type_per_pkg);

                                                         varhome      =  vh::select_varhome (constrained_pkg_varhome, slot_per_pkg);
                                                         inlining_data =  id::select (constrained_pkg_inline_info, slot_per_pkg);

                                                         (unify_typoids { type_per_api, type_per_pkg, inlining_data, name => api_element_symbol })
                                                               ->
                                                               (types, generalized_typevars);

                                                         path = syp::SYMBOL_PATH [api_element_symbol];

                                                         pkg_var =  vac::PLAIN_VARIABLE
                                                                      {
                                                                        path,
                                                                        vartypoid_ref => REF type_per_pkg,
                                                                        #
                                                                        varhome,
                                                                        inlining_data
                                                                      };

                                                         my (abstract_declarations', new_var)
                                                             = 
                                                             case ( tj::head_reduce_typoid  type_per_pkg, 
                                                                    tj::head_reduce_typoid  type_per_api
                                                                  )

                                                                  ((tdt::TYPESCHEME_TYPOID _, _) | (_, tdt::TYPESCHEME_TYPOID _))
                                                                      => 
                                                                      {   varhome =  vh::named_varhome (api_element_symbol, make_var);
                                                                          #
                                                                          api_var = vac::PLAIN_VARIABLE
                                                                                      {
                                                                                        path,
                                                                                        vartypoid_ref => REF type_per_api,

                                                                                        inlining_data,
                                                                                        varhome
                                                                                      };

                                                                          if (*debugging and ((list::length generalized_typevars) > 0))

                                                                              printf "api-match-g.pkg: Creating ds::VALUE_NAMING node with length(generalized_typevars) d=%d  (I)\n" (list::length generalized_typevars);

                                                                              apply  unparse_typevar_ref  generalized_typevars
                                                                              where
                                                                                  unparse_typevar_ref
                                                                                      =
                                                                                      unparse_type::unparse_typevar_ref
                                                                                          symbolmapstack;
                                                                                  #
                                                                                  fun if_debugging_unparse_typevar_ref  (msg, typevar_ref)
                                                                                      = 
                                                                                      if *debugging             # Without this 'if' (and the matching one in unify_typoids), compiling the compiler takes 5X as long! :-)
                                                                                          typer_debugging::with_internals
                                                                                              (\\ () =  tyd::debug_print debugging (msg, unparse_typevar_ref, typevar_ref));
                                                                                      fi;
                                                                                  #
                                                                                  fun unparse_typevar_ref  typevar_ref
                                                                                      =
                                                                                      if_debugging_unparse_typevar_ref ("", typevar_ref);
                                                                              end;
                                                                              printf "\n";
                                                                          fi;

                                                                          named_value
                                                                              = 
                                                                              ds::VALUE_NAMING   { pattern              =>  ds::VARIABLE_IN_PATTERN api_var,
                                                                                                  expression           =>  ds::VARIABLE_IN_EXPRESSION {  var => REF pkg_var,  typescheme_args => types  },
                                                                                                  raw_typevars     =>  REF [],
                                                                                                  generalized_typevars
                                                                                                };

                                                                          ( (ds::VALUE_DECLARATIONS [named_value]) ! abstract_declarations,
                                                                            api_var
                                                                          );
                                                                      };

                                                                 _ => (abstract_declarations, pkg_var);

                                                             esac;

                                                         symbolmapstack_entries'
                                                             =
                                                             (sxe::NAMED_VARIABLE new_var) ! symbolmapstack_entries;

                                                         match_all_api_elements
                                                           (
                                                             remaining_api_elements,
                                                             typerstore,
                                                             module_declarations,
                                                             abstract_declarations',
                                                             symbolmapstack_entries',
                                                             match_succeeded
                                                           );
                                                     };

                                                 mld::VALCON_IN_API
                                                     {
                                                       slot,
                                                       sumtype => tdt::VALCON { typoid => type_per_pkg,
                                                                                  name,
                                                                                  is_constant,
                                                                                  form,
                                                                                  signature,
                                                                                  is_lazy
                                                                                }
                                                     }
                                                     => 
                                                     {   type_per_api = type_in_matched  ("@@@type_per_api (my/con)", type_per_api );
                                                         type_per_pkg = type_in_original ("@@@type_per_pkg (my/con)", type_per_pkg );

                                                         (unify_typoids { type_per_api, type_per_pkg, inlining_data => id::NIL, name })
                                                             ->
                                                             (types, generalized_typevars);

                                                         new_form
                                                             =
                                                             case slot 
                                                                 THE s =>  exception_representation (form, vh::select_varhome (constrained_pkg_varhome, s));
                                                                 NULL  =>  form;
                                                             esac;

                                                         my (abstract_declarations', symbolmapstack_entries')
                                                             =
                                                             {   valcon = tdt::VALCON
                                                                         {
                                                                           typoid => type_per_pkg,
                                                                           form => new_form,

                                                                           name,
                                                                           is_constant,
                                                                           signature,
                                                                           is_lazy
                                                                         };

                                                                 varhome =   vh::named_varhome (name, make_var);

                                                                 api_var =   vac::PLAIN_VARIABLE
                                                                               {
                                                                                 path          =>  syp::SYMBOL_PATH [name],
                                                                                 varhome,

                                                                                 inlining_data =>  id::NIL,
                                                                                 vartypoid_ref      =>  REF type_per_api
                                                                               };

                                                                 if (*debugging and ((list::length generalized_typevars) > 0))
                                                                     printf "api-match-g.pkg: Creating ds::VALUE_NAMING node with length(generalized_typevars) d=%d  (II)\n" (list::length generalized_typevars);
                                                                 fi;

                                                                 named_value = ds::VALUE_NAMING
                                                                                 {
                                                                                   pattern              =>  ds::VARIABLE_IN_PATTERN api_var,
                                                                                   expression           =>  ds::VALCON_IN_EXPRESSION  { valcon,  typescheme_args => types },
                                                                                   raw_typevars     =>  REF [],
                                                                                   generalized_typevars
                                                                                 };

                                                                 ( (ds::VALUE_DECLARATIONS  [named_value])  !   abstract_declarations, 
                                                                   (sxe::NAMED_VARIABLE api_var)              !   symbolmapstack_entries
                                                                 );
                                                             };

                                                         match_all_api_elements
                                                           (
                                                             remaining_api_elements,
                                                             typerstore,
                                                             module_declarations,
                                                             abstract_declarations', 
                                                             symbolmapstack_entries',
                                                             match_succeeded
                                                           );
                                                     };

                                                 _ => bug "match v elem.1";
                                             esac
                                             except mj::UNBOUND name
                                                    =
                                                    complain_and_loop (THE "value");


                                         mld::VALCON_IN_API
                                           {
                                             sumtype => tdt::VALCON
                                                             {
                                                               name,
                                                               typoid => type_per_api,
                                                               is_lazy,
                                                               form => form_per_api,
                                                               ...
                                                             },
                                             ...
                                           }
                                             => 
                                             case (mj::get_api_element (pkg_api_elements, name))
                                                 #
                                                  mld::VALCON_IN_API
                                                    {
                                                      sumtype => tdt::VALCON
                                                                      {
                                                                        typoid =>  type_per_pkg,
                                                                        form =>  form_per_pkg,
                                                                        is_constant, 
                                                                        signature,
                                                                        ...
                                                                      },
                                                      slot
                                                  }
                                                      =>
                                                      if ( vh::is_exception  form_per_api
                                                           ==
                                                           vh::is_exception  form_per_pkg
                                                         )

                                                           type_per_api =   type_in_matched ("@@@type_per_api (con/con)", type_per_api);
                                                           type_per_pkg =   type_in_original("@@@type_per_pkg (con/con)", type_per_pkg);

                                                           unify_typoids { type_per_api, type_per_pkg, inlining_data => id::NIL, name };

                                                           symbolmapstack_entries'
                                                               =
                                                               case slot
                                                                   #
                                                                   NULL => symbolmapstack_entries; 

                                                                   THE s
                                                                       => 
                                                                       {   varhome   =   vh::select_varhome (constrained_pkg_varhome, s);

                                                                           new_form =   exception_representation (form_per_pkg, varhome); 

                                                                           con = tdt::VALCON
                                                                                   {
                                                                                     typoid =>  type_per_pkg,
                                                                                     form =>  new_form,

                                                                                     name,
                                                                                     is_constant,

                                                                                     is_lazy,
                                                                                     signature
                                                                                   };

                                                                           (sxe::NAMED_CONSTRUCTOR con) ! symbolmapstack_entries;
                                                                       };
                                                                  esac;

                                                           match_all_api_elements
                                                               (
                                                                 remaining_api_elements,
                                                                 typerstore,
                                                                 module_declarations,
                                                                 abstract_declarations,
                                                                 symbolmapstack_entries',
                                                                 match_succeeded
                                                               );

                                                      else
                                                          raise exception mj::UNBOUND name;
                                                      fi;

                                                  mld::VALUE_IN_API _
                                                      =>
                                                      if   (vh::is_exception  form_per_api)   complain_and_loop (THE "exception"  );
                                                      else                                    complain_and_loop (THE "constructor");
                                                      fi;

                                                 _ => bug "match v elem.2";
                                             esac
                                             except
                                                 mj::UNBOUND name
                                                 =
                                                 if   (vh::is_exception  form_per_api)   complain_and_loop (THE "exception"  );
                                                 else                                    complain_and_loop (THE "constructor");
                                                 fi;


                                        _ => bug "match_all_api_elements";
                                  esac;

                                };
                        end;            # fun  match_all_api_elements 
                    end;                # Stipulate.

                    #
                    fun match_pkg_to_api  typerstore
                        = 
                        {   if_debugging_say "match_pkg_to_api/TOP";

                            my  ( abstract_declarations,                        # Goes into      thinned_declarations.
                                  symbolmapstack_entries,                       # Contributes to thinned_declarations, also inlining_data in thinned_package.
                                  typerstore,                                   # Goes into      thinned_package.
                                  module_declarations,                          # Goes into      coerced_package_expression. 
                                  match_succeeded
                                )
                                = 
                                match_all_api_elements
                                    (
                                      constraining_api_elements,
                                      typerstore,       # 
                                      [],                       # module_declarations
                                      [],                       # abstract_declarations
                                      [],                       # symbolmapstack_entries
                                      TRUE                      # match_succeeded
                                    )
                                except
                                    tro::UNBOUND
                                        =
                                        {   if_debugging_say "match_pkg_to_api 1: UNBOUND raised.";

                                            raise exception tro::UNBOUND;
                                        };

                            if match_succeeded

                                 typerstore
                                     =
                                     tro::mark (make_fresh_stamp, typerstore);

                                 if_debugging_say "--match_pkg_to_api: elements matched successfully";

                                 check_sharing (constraining_api, typerstore)
                                 except
                                     tro::UNBOUND
                                         =
                                         {   if_debugging_say "@@@match_pkg_to_api 3";

                                             raise exception tro::UNBOUND;
                                         };

                                 if_debugging_say "--match_pkg_to_api: sharing checked";

                                 thinned_package
                                     =
                                     mld::A_PACKAGE {
                                         an_api        =>  constraining_api,
                                         varhome       =>  vh::make_varhome  make_var,
                                         inlining_data =>  id::LIST (map mj::extract_inlining_data  symbolmapstack_entries),
                                         typechecked_package
                                             =>
                                             {   stamp            =>  pkg_stamp,
                                                 property_list    =>  property_list::make_property_list (),
                                                 stub             =>  NULL,
                                                 typerstore,
                                                 inverse_path
                                             }
                                       };

                                 thinned_declarations
                                     = 
                                     ds::PACKAGE_DECLARATIONS [
                                         ds::NAMED_PACKAGE {
                                             name_symbol =>  package_name,
                                             a_package   =>  thinned_package,
                                             definition
                                                 =>
                                                 ds::PACKAGE_LET
                                                   {
                                                     declaration => ds::SEQUENTIAL_DECLARATIONS  abstract_declarations,
                                                     expression  => ds::PACKAGE_DEFINITION       symbolmapstack_entries
                                                   }
                                         }
                                     ];

                                 coerced_package_expression 
                                     =
                                     mld::PACKAGE { stamp              =>  mld::GET_STAMP (mld::VARIABLE_PACKAGE (reverse rpath)),
                                                    module_declaration =>  mld::SEQUENTIAL_DECLARATIONS  module_declarations
                                                  };

                                 if_debugging_say "match_pkg_to_api/BOT";

                                 ( thinned_declarations,
                                   thinned_package,
                                   coerced_package_expression
                                 );

                            else        # !match_succeeded

                                 ( ds::SEQUENTIAL_DECLARATIONS [],
                                   mld::ERRONEOUS_PACKAGE,
                                   mld::CONSTANT_PACKAGE (mld::bogus_typechecked_package)
                                 );
                            fi;
                        };                      # fun match_pkg_to_api


                    # We should not do such short-cut matching because we need to
                    # recalculuate the Typepath information for generic
                    # components.
                    #
                    # But completely turning this off is a bit too expensive, so 
                    # we add a contains_generic in the api to indicate whether it 
                    # contains generic components. 
                    #   
                    if ( (sta::same_stamp (constraining_api_stamp, pkg_api_stamp))
                         and      constraining_api_is_closed
                         and (not constraining_api_contains_generic)
                       )

                         # Short-cut matching:
                         # 
                         ( ds::SEQUENTIAL_DECLARATIONS [],
                           constrained_pkg,
                           mld::VARIABLE_PACKAGE (reverse rpath)
                         );
                    else
                         match_pkg_to_api
                             (
                               constraining_api_is_closed
                                   ?? tro::empty
                                   :: match_typerstore
                             );
                    fi;
                };

            thin_package' _
                =>
                ( ds::SEQUENTIAL_DECLARATIONS [],
                  mld::ERRONEOUS_PACKAGE,
                  bogus_package_expression
                );

        end                     # fun thin_package' 


        ########################################################################################
        #
        # fun thin_package
        #
        # This gets invoked (only) from two points in
        #
        #     src/lib/compiler/front/typer/main/type-package-language-g.pkg
        #
        also
        fun thin_package
            {
              constrained_package:      mld::Package,
              constraining_api:         mld::Api,

              package_expression:       mld::Package_Expression,

              module_stamp_or_null:     Null_Or(sta::Stamp),

              debruijn_depth:           di::Debruijn_Depth,
              typerstore:               mld::Typerstore,
              inverse_path:             ip::Inverse_Path,
              symbolmapstack:           syx::Symbolmapstack,
              source_code_region:       lnd::Source_Code_Region,

              per_compile_stuff => per_compile_stuff as { make_fresh_stamp, ... }: trj::Per_Compile_Stuff
            }
            :
            { result_declaration:          ds::Declaration,             # Package type info for the resulting deep syntax tree. (ds::PACKAGE_LET.declaration)
              result_package:              mld::Package,                # Package code info for the resulting deep syntax tree. (ds::PACKAGE_LET.expression )
              coerced_package_expression:  mld::Package_Expression      # This winds up in module_declarations (i.e., internal to typechecker).
            }
            =
            {   if_debugging_say "thin_package/TOP";

                uncoerced_module_stamp
                    =
                    case module_stamp_or_null
                        #
                        THE x =>  x;
                        NULL  =>  make_fresh_stamp ();
                    esac;

                my (result_declaration, result_package, coercion_expression)
                    = 
                    thin_package'  ( constrained_package,
                                     constraining_api,
                                     
                                     anonymous_package_symbol,                  #  Added.  
                                     debruijn_depth,
                                     typerstore,
                                     [ uncoerced_module_stamp ],                #  Added.  
                                     inverse_path, 
                                     symbolmapstack,
                                     source_code_region,
                                     per_compile_stuff
                                   );

                coerced_package_expression
                    =
                    mld::COERCED_PACKAGE
                        {
                          boundvar => uncoerced_module_stamp,
                          raw      => package_expression,
                          coercion => coercion_expression
                        };

          #     result_expression = mld::PACKAGE_LET { declaration => mld::PACKAGE_DECLARATION (uncoerced_module_stamp, package_expression), expression };
          #     result_expression = mld::APPLY (mld::LAMBDA { parameter=uncoerced_module_stamp, body=expression }, package_expression) ;

                if_debugging_say "thin_package/BOT";

                { result_declaration,           # ds::Declaration,
                  result_package,               # mld::Generic,
                  coerced_package_expression    # mld::Package_Expression -- coerced version of original package_expression.
                };
            }
            except tro::UNBOUND
                   =
                   {   if_debugging_say "thin_package: UNBOUND was thrown.  src/lib/compiler/front/typer/modules/api-match-g.pkg";
                       raise exception tro::UNBOUND;
                   }


        ########################################################################## 
        #
        # Matching a generic package against a generic api:
        #
        #
        #  Arguments: funsig  F (fsigParVariable:  fsigParSig) = fsigBodySig
        #             generic package F (genericParVariable:  genericParSig) : genericBodySig = bodyExpression
        #
        #  Result:    generic package F (genericParVariable:  genericParSig) : genericBodySig = resultBodyExpression
        #
        ########################################################################## 

        also
        fun match_generic1
            (
              spec_api
                  as
                  mld::GENERIC_API
                      { parameter_api      => fsig_param_sig,
                        parameter_variable => fsig_param_variable,
                        parameter_symbol,
                        body_api           => fsig_body_sig,
                            ...
                      }
                  :
                  mld::Generic_Api,

              a_generic
                  as
                  mld::GENERIC { typechecked_generic,
                            ...
                          }
                  :
                  mld::Generic,

              generic_name:             sy::Symbol,
              debruijn_depth:           di::Debruijn_Depth,
              typerstore:               mld::Typerstore,
              uncoerced_generic:        mld::Generic_Expression,
              inverse_path:             ip::Inverse_Path,
              symbolmapstack:           syx::Symbolmapstack,
              source_code_region:       lnd::Source_Code_Region,

              per_compile_stuff
                  as
                  { make_fresh_stamp,
                    issue_highcode_codetemp => make_var,
                    ...
                  }
                  : trj::Per_Compile_Stuff
            )
            :
            ( ds::Declaration,
              mld::Generic,
              mld::Generic_Expression
            )
                =>
                (   {   # ** the typechecked_package var for the source generic "uncoerced_generic" 
                        uncoerced = make_fresh_stamp();

                        src_generic_expression
                            =
                            mld::VARIABLE_GENERIC [uncoerced];

                        generic_api_parameter_typechecked_package_symbol
                            =
                            case parameter_symbol
                                THE x => x; 
                                NULL  => generic_api_parameter_typechecked_package_symbol;
                            esac;

                        # ** parameter api instantiation **

                        my  { typechecked_package        => fsig_par_typechecked_package,
                              typepaths => param_tps
                            }
                            = 
                            gxs::do_generic_parameter_api {

                                an_api       =>  fsig_param_sig,
                                inverse_path =>  ip::INVERSE_PATH [generic_api_parameter_typechecked_package_symbol],

                                typerstore,
                                debruijn_depth,
                                source_code_region,
                                per_compile_stuff
                            };

                        debruijn_depth'   = di::next  debruijn_depth;

                        fsig_par_inst
                            = 
                            {   fsig_par_varhome = vh::make_varhome  make_var;
                                #
                                mld::A_PACKAGE { an_api              =>  fsig_param_sig,
                                                 typechecked_package =>  fsig_par_typechecked_package, 
                                                 varhome             =>  fsig_par_varhome,
                                                 inlining_data       =>  id::NIL
                                               };
                            };

                        # ** applying aGeneric to the fsigParInst package **

                        param_id = fsig_param_variable;    #  make_fresh_stamp()

                        my  { result_declaration =>  result_declaration1,
                              result_package     =>  result_package1,
                              result_expression  =>  result_expression1
                            }
                            = 
                            {   param_expression
                                    =
                                    mld::VARIABLE_PACKAGE [param_id];

                                apply_generic {
                                    a_generic,
                                    generic_expression   => src_generic_expression,
                                    arg_package          => fsig_par_inst, 

                                    arg_expression       => param_expression,
                                    debruijn_depth       => debruijn_depth', 

                                    module_stamp_or_null => NULL,
                                    stamppath_context  => epc::init_context /* ? ZHONG */,

                                    inverse_path         => ip::empty,

                                    symbolmapstack,
                                    source_code_region,
                                    per_compile_stuff
                                };
                            };

                        # Matching the result package against the body api

                        fsig_body_sig_dictionary
                            =
                            tro::set (
                                typerstore,
                                fsig_param_variable,
                                mld::PACKAGE_ENTRY fsig_par_typechecked_package
                            );

                        my  { result_declaration         =>  result_declaration2,
                              result_package             =>  result_package2,
                              coerced_package_expression =>  result_expression2
                            }
                            = 
                            {   rp = ip::INVERSE_PATH [ sy::make_package_symbol "<GenericResult>" ];

                                thin_package  { constraining_api       =>  fsig_body_sig,
                                                constrained_package    =>  result_package1,

                                                package_expression     =>  result_expression1,
                                                module_stamp_or_null   => NULL,

                                                debruijn_depth         => debruijn_depth',
                                                typerstore             => fsig_body_sig_dictionary,
                                                inverse_path           => rp, 

                                                symbolmapstack,
                                                source_code_region,
                                                per_compile_stuff
                                              };
                            };

                        # Construct the Typepath for the resulting generic:
                        #
                        result_tps
                            = 
                            case result_package2 

                                 mld::A_PACKAGE { an_api, typechecked_package, ... }
                                     =>
                                     gxs::get_packages_typepaths
                                         {
                                           typerstore  => fsig_body_sig_dictionary, 
                                           an_api,
                                           typechecked_package,
                                           per_compile_stuff
                                         };

                                _ => [];
                            esac;

                        # Construct the resulting coerced generic:
                        #
                        result_generic
                            =
                            {   result_expression3
                                    =
                                    mld::PACKAGE_LET
                                      {

                                        declaration
                                            =>
                                            mld::GENERIC_DECLARATION (
                                                uncoerced,
                                                mld::CONSTANT_GENERIC typechecked_generic
                                            ), 

                                        expression
                                            =>
                                            result_expression2
                                      };

                                result_closure
                                    =
                                    mld::GENERIC_CLOSURE {

                                        parameter_module_stamp =>  param_id,
                                        body_package_expression            =>  result_expression3,
                                        typerstore
                                    };

                                tps = tdt::TYPEPATH_GENERIC (param_tps, result_tps);

                                result_typechecked_package
                                    =
                                    {   stamp                 =>  typechecked_generic.stamp,    # ** DAVE ? XXX BUGGO FIXME **
                                        generic_closure       =>  result_closure,

                                        typepath =>  THE tps,
                                        property_list         =>  property_list::make_property_list (),
                                        stub                  =>  NULL,

                                        inverse_path
                                    };

                                mld::GENERIC { a_generic_api     =>  spec_api,
                                             typechecked_generic =>  result_typechecked_package,
                                             varhome             =>  vh::make_varhome  make_var,
                                             inlining_data       =>  id::NIL
                                           };
                            };

                        # The resulting generic deep_syntax_tree
                        #
                        fdec = {   body_abs
                                       =
                                       ds::PACKAGE_LET
                                         {
                                           declaration =>  ds::SEQUENTIAL_DECLARATIONS [ result_declaration1, result_declaration2 ],
                                           expression  =>  ds::PACKAGE_BY_NAME result_package2
                                         };

                                   generic_expression
                                       =
                                       ds::GENERIC_DEFINITION {

                                           parameter       =>  fsig_par_inst,
                                           parameter_types =>  param_tps,
                                           definition      =>  body_abs
                                       };

                                    ds::GENERIC_DECLARATIONS [

                                        ds::NAMED_GENERIC {

                                            name_symbol => anonymous_generic_symbol,
                                            a_generic   => result_generic,
                                            definition  => generic_expression
                                        }
                                    ];
                               };

                        # ** the generic typechecked_package expression **

                        generic_expression
                            = 
                            mld::LET_GENERIC (

                                mld::GENERIC_DECLARATION (uncoerced, uncoerced_generic), 

                                mld::LAMBDA_TP {

                                    parameter =>  param_id,
                                    body      =>  result_expression2,
                                    an_api    =>  spec_api
                                }
                            );

                        (fdec, result_generic, generic_expression);

                    }
                    except
                        MATCH
                            =
                            (   ds::SEQUENTIAL_DECLARATIONS [],
                                mld::ERRONEOUS_GENERIC,
                                bogus_generic_expression
                            )
                );

             # This is intended to handle only the two left-hand side 
             # occurrences of PACKAGE { ... } above, and is very crude. 
             # It should be replaced by case-expressions on the results of 
             # match etc.    XXX BUGGO FIXME


            match_generic1 _
                =>
                (ds::SEQUENTIAL_DECLARATIONS [], mld::ERRONEOUS_GENERIC, bogus_generic_expression);

        end                             # fun match_generic1


        ####################################################################################
        #
        # my match_generic
        #
        ####################################################################################

        also
        fun match_generic
            {
              an_api:                   mld::Generic_Api,
              a_generic:                mld::Generic,
              generic_expression:       mld::Generic_Expression,
              debruijn_depth:           di::Debruijn_Depth,
              typerstore:               mld::Typerstore,
              inverse_path:             ip::Inverse_Path, 
              symbolmapstack:           syx::Symbolmapstack,
              source_code_region:       lnd::Source_Code_Region,
              per_compile_stuff:                trj::Per_Compile_Stuff
            }
            :
            { result_declaration:      ds::Declaration,
              result_generic:          mld::Generic,
              result_expression:       mld::Generic_Expression
            } 
            = 
            {   if_debugging_say "match_generic/TOP";

                my (result_declaration, result_generic, result_expression)
                    = 
                    match_generic1 (
                        an_api,
                        a_generic,
                        anonymous_generic_symbol,
                        debruijn_depth,
                        typerstore,
                        generic_expression,
                        inverse_path, 
                        symbolmapstack,
                        source_code_region,
                        per_compile_stuff
                    );

                if_debugging_say "match_generic/BOT";


                { result_declaration,
                  result_generic,
                  result_expression
                };
            }
            except tro::UNBOUND
                   =
                   {   if_debugging_say "@@@matchGeneric";
                       raise exception tro::UNBOUND;
                   }


        ##########################################################################
        #
        # Packing a package against a api.
        #
        ##########################################################################

        also
        fun cast_package'
                (
                  # Constrained package:
                  #
                  mld::A_PACKAGE { varhome              =>  constrained_package_varhome,
                                 typechecked_package =>  { typerstore => constrained_package_typerstore, ... },
                                 inlining_data       =>  constrained_package_inlining_data,
                                 ...
                               }
                      :
                      mld::Package,

                  constraining_api
                      as
                      mld::API { api_elements, ... }
                      :
                      mld::Api,

                  result_typechecked_package
                      as
                      { typerstore => result_typerstore, ... }
                      :
                      mld::Typechecked_Package,

                  abstract_types:               tj::Typeset,
                  package_name:                 sy::Symbol,
                  depth:                        Int,

                  typerstore:                   mld::Typerstore,
                  inverse_path:                 ip::Inverse_Path,

                  symbolmapstack:               syx::Symbolmapstack,
                  source_code_region:           lnd::Source_Code_Region, 

                  per_compile_stuff
                      as
                      { issue_highcode_codetemp=>make_var, error_fn, ... }
                      :
                      trj::Per_Compile_Stuff 
                ) 
                :
                ( ds::Declaration,
                  mld::Package
                )

                =>
                {   fun type_in_result (kind, type)
                        = 
                        (mj::translate_typoid
                           result_typerstore
                           type
                        ) 
                        except
                            tro::UNBOUND
                            =
                            {   tyd::debug_print  debugging  (kind, unparse_type::unparse_typoid  symbolmapstack, type);
                                raise exception tro::UNBOUND;
                            };


                    #
                    fun type_in_source (kind, type)
                        = 
                        (mj::translate_typoid
                           constrained_package_typerstore
                           type
                        ) 
                        except
                            tro::UNBOUND
                            =
                            {   tyd::debug_print  debugging  (kind, unparse_type::unparse_typoid  symbolmapstack, type);
                                raise exception tro::UNBOUND;
                            };


                    #
                    fun cast_api_elements ([], typerstore, declarations, symbolmapstack_entries)
                            =>
                            ( reverse declarations,
                              reverse symbolmapstack_entries
                            );

                        cast_api_elements
                            ( (symbol, api_element) ! remaining_api_elements,
                              typerstore,
                              declarations,
                              symbolmapstack_entries
                            )
                            => 
                            {                                                                                                   if_debugging_say "cast_api_elements/TOP";
                                case api_element
                                    #
                                    mld::PACKAGE_IN_API
                                        {
                                          an_api       => this_spec_api,
                                          module_stamp,
                                          slot,
                                          ...
                                        }
                                        =>
                                        case ( tro::find_entry_by_module_stamp (result_typerstore,  module_stamp),
                                               tro::find_entry_by_module_stamp (constrained_package_typerstore,  module_stamp)
                                             )  

                                             ( mld::PACKAGE_ENTRY result_typechecked_package,
                                               mld::PACKAGE_ENTRY source_typechecked_package
                                             )
                                                 =>
                                                 {   source_package
                                                         =
                                                         mld::A_PACKAGE {
                                                             an_api              => this_spec_api,
                                                             typechecked_package => source_typechecked_package,

                                                             varhome             => vh::select_varhome          (constrained_package_varhome,      slot),
                                                             inlining_data       => id::select (constrained_package_inlining_data, slot)
                                                         };

                                                     inverse_path'
                                                         =
                                                         ip::extend (inverse_path, symbol);

                                                     my (thinned_declaration, thinned_package)
                                                         = 
                                                         cast_package' (

                                                             source_package,
                                                             this_spec_api,

                                                             result_typechecked_package,
                                                             abstract_types,
                                                             symbol,
                                                             depth,
                                                             typerstore,
                                                             inverse_path',
                                                             symbolmapstack, 
                                                             source_code_region,
                                                             per_compile_stuff
                                                         );

                                                     typerstore'
                                                         = 
                                                         {   typechecked_package
                                                                 = 
                                                                 case thinned_package

                                                                      mld::A_PACKAGE { typechecked_package, ... } => typechecked_package;
                                                                      _                                         => mld::bogus_typechecked_package;
                                                                 esac;

                                                             tro::set (
                                                                 typerstore,
                                                                 module_stamp,
                                                                 mld::PACKAGE_ENTRY typechecked_package
                                                             );
                                                         };

                                                     declarations'         = thinned_declaration                  ! declarations;
                                                     symbolmapstack_entries' = (sxe::NAMED_PACKAGE thinned_package) ! symbolmapstack_entries;

                                                     cast_api_elements (remaining_api_elements, typerstore', declarations', symbolmapstack_entries');
                                                 };

                                             _   =>
                                                 # Missing element, error situation -- do nothing:
                                                 #
                                                 cast_api_elements (remaining_api_elements, typerstore, declarations, symbolmapstack_entries);
                                        esac;

                                    mld::GENERIC_IN_API {   a_generic_api => this_spec_api,   module_stamp,   slot }
                                        => 
                                        case ( tro::find_entry_by_module_stamp (result_typerstore, module_stamp),
                                               tro::find_entry_by_module_stamp (constrained_package_typerstore, module_stamp)
                                             )

                                             ( mld::GENERIC_ENTRY result_typechecked_generic,
                                               mld::GENERIC_ENTRY source_typechecked_generic
                                             )
                                                 =>
                                                 {   src_generic
                                                         =
                                                         mld::GENERIC {
                                                             a_generic_api       =>  this_spec_api,
                                                             typechecked_generic =>  source_typechecked_generic,
                                                             varhome             =>  vh::select_varhome          (constrained_package_varhome,      slot),
                                                             inlining_data       =>  id::select (constrained_package_inlining_data, slot)
                                                         };

                                                     inverse_path'
                                                         =
                                                         ip::extend (inverse_path, symbol);

                                                     my (thinned_declaration, thinned_g)
                                                         = 
                                                         pack_generic1 (
                                                             this_spec_api,
                                                             result_typechecked_generic,
                                                             src_generic,
                                                             abstract_types,
                                                             symbol,
                                                             depth,
                                                             typerstore,
                                                             inverse_path',
                                                             symbolmapstack,
                                                             source_code_region,
                                                             per_compile_stuff
                                                         );

                                                     typerstore'
                                                         = 
                                                         {   typechecked_generic
                                                                 = 
                                                                 case thinned_g
                                                                      mld::GENERIC { typechecked_generic, ... } =>  typechecked_generic;
                                                                     _                                        =>  mld::bogus_typechecked_generic;
                                                                 esac;

                                                             tro::set (typerstore, module_stamp, mld::GENERIC_ENTRY typechecked_generic);
                                                         };

                                                     declarations'         = thinned_declaration            ! declarations;
                                                     symbolmapstack_entries' = (sxe::NAMED_GENERIC thinned_g) ! symbolmapstack_entries;

                                                     cast_api_elements (remaining_api_elements, typerstore', declarations', symbolmapstack_entries');
                                                 };

                                            _   =>
                                                cast_api_elements (remaining_api_elements, typerstore, declarations, symbolmapstack_entries);

                                        esac;

                                    mld::VALUE_IN_API { typoid => spec_type,   slot }
                                        => 
                                        {   result_type   =  type_in_result ("@@@spec-resty (cast_package-my)", spec_type);
                                            source_type   =  type_in_source ("@@@spec-srcty (cast_package-my)", spec_type);

                                            varhome       =  vh::select_varhome          (constrained_package_varhome,      slot);
                                            inlining_data =  id::select (constrained_package_inlining_data, slot);

                                            (try_unifying_pkg_with_api_type (result_type, source_type, inlining_data))
                                                ->
                                                (types, generalized_typevars, type, result_unified_with_source_type);

                                            path  = syp::SYMBOL_PATH [symbol];

                                            srcvar =    vac::PLAIN_VARIABLE
                                                          {
                                                            path,
                                                            vartypoid_ref => REF source_type,
                                                            varhome,
                                                            inlining_data
                                                          };

                                            my (declarations', named_variable)
                                                =
                                                if result_unified_with_source_type
                                                    #
                                                    (declarations, srcvar);
                                                else
                                                    varhome = vh::named_varhome (symbol, make_var);

                                                    result_variable
                                                        = 
                                                        vac::PLAIN_VARIABLE
                                                          { path,
                                                            vartypoid_ref      =>  REF result_type,
                                                            inlining_data =>  id::NIL,
                                                            varhome
                                                          };

                                                    ntypes =   tj::filter_typeset (type, abstract_types);

                                                    expression
                                                        = 
                                                        ds::ABSTRACTION_PACKING_EXPRESSION (
                                                            #
                                                            ds::VARIABLE_IN_EXPRESSION {  var => REF srcvar,  typescheme_args => types  },
                                                            type,
                                                            ntypes
                                                        );

                                                    if (*debugging and ((list::length generalized_typevars) > 0))
                                                        printf "api-match-g.pkg: Creating ds::VALUE_NAMING node with length(generalized_typevars) d=%d  (III)\n" (list::length generalized_typevars);
                                                    fi;

                                                    named_value =   ds::VALUE_NAMING
                                                                      {
                                                                        pattern              => (ds::VARIABLE_IN_PATTERN  result_variable),
                                                                        expression,
                                                                        raw_typevars     => REF [],
                                                                        generalized_typevars
                                                                      };

                                                    ( (ds::VALUE_DECLARATIONS [named_value])   !   declarations,
                                                       result_variable
                                                    );
                                                fi;


                                            symbolmapstack_entries'
                                                =
                                                (sxe::NAMED_VARIABLE named_variable)
                                                !
                                                symbolmapstack_entries;

                                            cast_api_elements
                                              (
                                                remaining_api_elements,
                                                typerstore,
                                                declarations',
                                                symbolmapstack_entries'
                                              );
                                        };


                                    mld::VALCON_IN_API
                                      {
                                        sumtype => tdt::VALCON
                                                        {
                                                          name,
                                                          typoid,
                                                          form,
                                                          is_constant,
                                                          signature,
                                                          is_lazy
                                                        },
                                        slot
                                      }
                                        =>
                                        {   symbolmapstack_entries'
                                                =
                                                case slot 
                                                    #   
                                                    NULL =>     symbolmapstack_entries; 

                                                    THE s =>    {   result_type
                                                                        =
                                                                        type_in_result ("@@@spec-resty (cast_package-con)", typoid);

                                                                    varhome =  vh::select_varhome (constrained_package_varhome, s);

                                                                    con = tdt::VALCON { typoid => result_type,
                                                                                       form => exception_representation (form, varhome),
                                                                                       name,

                                                                                       is_lazy,
                                                                                       is_constant,

                                                                                       signature
                                                                                     };

                                                                    (sxe::NAMED_CONSTRUCTOR (con)) ! symbolmapstack_entries;
                                                                };
                                                esac;

                                            cast_api_elements
                                              (
                                                remaining_api_elements,
                                                typerstore,
                                                declarations,
                                                symbolmapstack_entries'
                                              );
                                        };


                                    mld::TYPE_IN_API { type => type_per_api,   module_stamp,   is_a_replica,   scope }
                                        =>
                                        {   typerstore'
                                                =
                                                tro::set (
                                                    typerstore,
                                                    module_stamp,
                                                    tro::find_entry_by_module_stamp (result_typerstore, module_stamp)
                                                );

                                            cast_api_elements
                                              (
                                                remaining_api_elements,
                                                typerstore',
                                                declarations,
                                                symbolmapstack_entries
                                              );
                                        };

                                esac;

                            };
                    end;                        #  fun cast_api_elements 


                    my  ( abstract_declarations,
                          symbolmapstack_entries
                        )
                        =
                        cast_api_elements (
                            api_elements,
                            typerstore,
                            [],                         # declarations accumulator.
                            []                          # symbolmapstack_entries accumulator.
                        );

                    result_package
                        =
                        mld::A_PACKAGE
                          {
                            typechecked_package  =>  result_typechecked_package,
                            #
                            an_api        =>  constraining_api,
                            varhome       =>  vh::make_varhome  make_var,
                            inlining_data =>  id::LIST (map  mj::extract_inlining_data  symbolmapstack_entries)
                          };

                    result_declaration
                        = 
                        ds::PACKAGE_DECLARATIONS
                          [
                            ds::NAMED_PACKAGE
                              {
                                name_symbol =>  package_name,
                                a_package   =>  result_package,

                                definition
                                    =>
                                    ds::PACKAGE_LET
                                      {
                                        declaration =>  ds::SEQUENTIAL_DECLARATIONS  abstract_declarations,
                                        expression  =>  ds::PACKAGE_DEFINITION       symbolmapstack_entries
                                      }
                              }
                          ];

                    ( result_declaration,
                      result_package
                    );
                };

            cast_package' _
                =>
                ( ds::SEQUENTIAL_DECLARATIONS [],
                  mld::ERRONEOUS_PACKAGE
                );
        end                             # fun cast_package'


        ########################################################################################
        # Abstraction matching of a package against an api.
        #
        # INVARIANT: The base api for pkg should be exactly an_api; in other
        #            words, a_package should have been matched against an_api before
        #            being packed against an_api.
        #
        # This gets invoked (only) from
        #     src/lib/compiler/front/typer/main/type-package-language-g.pkg
        #
        ########################################################################################

        also
        fun cast_package
            {
              constrained_package:      mld::Package,
              constraining_api:         mld::Api,

              package_expression:       mld::Package_Expression,
              debruijn_depth:           di::Debruijn_Depth,
              typerstore:               mld::Typerstore,
              inverse_path:             ip::Inverse_Path, 
              symbolmapstack:           syx::Symbolmapstack,
              source_code_region:       lnd::Source_Code_Region,
              per_compile_stuff:                trj::Per_Compile_Stuff 
            }
            :
            { result_declaration:       ds::Declaration,
              result_package:           mld::Package,
              result_expression:        mld::Package_Expression  
            } 
            = 
            {   if_debugging_say "cast_package/TOP";

                my  { typechecked_package        =>  result_typechecked_package,
                      abstract_types,

                      type_stamppaths =>  _
                    }
                    = 
                    {   source_typechecked_package
                            =
                            case constrained_package
                                #
                                mld::A_PACKAGE { typechecked_package, ... }
                                    =>
                                    typechecked_package;

                                _   => mld::bogus_typechecked_package;
                            esac;


                        gxs::instantiate_package_abstractions
                          {
                            an_api => constraining_api,
                            typerstore,
                            source_typechecked_package,

                            inverse_path,
                            source_code_region,
                            per_compile_stuff
                          };
                    };

                if_debugging_say "cast_package - processing done";

                abstract_types'
                    =
                    fold_backward
                        tj::insert_type_into_typeset
                        (tj::make_typeset())
                        abstract_types;

                my (result_declaration, result_package)
                    = 
                    cast_package'
                      (
                        constrained_package,
                        constraining_api,

                        result_typechecked_package,
                        abstract_types',
                        anonymous_package_symbol,
                        debruijn_depth,
                        typerstore,
                        inverse_path,
                        symbolmapstack,
                        source_code_region,
                        per_compile_stuff
                      );

                if_debugging_say "cast_package - cast_package' done";

                result_expression
                    =
                    mld::ABSTRACT_PACKAGE (
                        constraining_api,
                        package_expression
                    );

                if_debugging_say "cast_package/BOT";


                { result_declaration,
                  result_package,
                  result_expression
                };
            }                                           # fun cast_package


        ############################################################################
        # 
        # fun pack_generic1:  Packing a generic package against a generic api.
        #
        ############################################################################

        also
        fun pack_generic1
            ( spec_api
                  as mld::GENERIC_API { parameter_api, parameter_variable, body_api, ... }
                  :  mld::Generic_Api,

              result_typechecked_generic:  mld::Typechecked_Generic,

              src_generic
                  as mld::GENERIC { typechecked_generic => source_typechecked_generic, ... }
                  :  mld::Generic,

              abstract_types1:          type_junk::Typeset,
              generic_name:             sy::Symbol,
              debruijn_depth:           di::Debruijn_Depth,
              typerstore:               mld::Typerstore,
              inverse_path:             ip::Inverse_Path,
              symbolmapstack:           syx::Symbolmapstack,
              source_code_region:       lnd::Source_Code_Region,

              per_compile_stuff
                  as { make_fresh_stamp, issue_highcode_codetemp=>make_var, error_fn, ... }
                  :  trj::Per_Compile_Stuff
            )
            :
            ( ds::Declaration,
              mld::Generic
            )
                => 
                {   my  { typechecked_package        =>  param_typechecked_package,
                          typepaths =>  param_tps
                        }
                        =
                        gxs::do_generic_parameter_api {

                            an_api              =>  parameter_api,
                            typerstore,
                            inverse_path        =>  ip::INVERSE_PATH [generic_api_parameter_typechecked_package_symbol],
                            debruijn_depth,
                            source_code_region,
                            per_compile_stuff
                        };

                    debruijn_depth'
                        =
                        di::next  debruijn_depth;

                    parameter_package
                        = 
                        {   param_varhome
                                =
                                vh::make_varhome  make_var;

                            mld::A_PACKAGE { an_api            => parameter_api,
                                           typechecked_package => param_typechecked_package,

                                           varhome             => param_varhome,
                                           inlining_data       => id::NIL
                                         };
                        };

                    my  { result_declaration => rdec1,
                          result_package     => body_package,
                          result_expression  => _
                        }
                        = apply_generic { a_generic            => src_generic,
                                          generic_expression   => mld::CONSTANT_GENERIC source_typechecked_generic,
                                          arg_package          => parameter_package, 

                                          arg_expression       =>  mld::CONSTANT_PACKAGE param_typechecked_package,
                                          debruijn_depth       =>  debruijn_depth', 
                                          inverse_path         =>  ip::empty,

                                          module_stamp_or_null =>  NULL,
                                          stamppath_context  =>  epc::init_context,                     #  ? ZHONG 

                                          symbolmapstack,
                                          source_code_region,
                                          per_compile_stuff
                                        };

                    #  typechecked_body = expand_generic::expand_generic (srcGenericMacroExpansion, paramMacroExpansion, debruijn_depth', stamppath_context, per_compile_stuff) ;
                    #
                    typechecked_body
                        = 
                        case body_package

                             mld::A_PACKAGE { typechecked_package, ... } => typechecked_package;
                            _ => mld::bogus_typechecked_package;
                        esac;

                    my  {  typechecked_package              => result_typechecked_package,
                           abstract_types   => abstract_types2,
                           type_stamppaths => _
                        }
                        = 
                        {   typerstore'
                                = 
                                tro::mark (  make_fresh_stamp,
                                             tro::set (typerstore, parameter_variable, mld::PACKAGE_ENTRY param_typechecked_package)
                                          );

                            gxs::instantiate_package_abstractions {

                                an_api                     =>  body_api,
                                typerstore     =>  typerstore',
                                source_typechecked_package =>  typechecked_body,
                                inverse_path,
                                source_code_region,
                                per_compile_stuff
                            };
                        };

                    abstract_types
                        =
                        fold_backward
                            tj::insert_type_into_typeset
                            abstract_types1
                            abstract_types2;

                    my (rdec2, result_package)
                        = 
                        {   inverse_path'
                                =
                                ip::INVERSE_PATH
                                    [ sy::make_package_symbol "<GenericResult>" ];

                            cast_package' (

                                body_package,
                                body_api,

                                result_typechecked_package,
                                abstract_types,
                                anonymous_package_symbol,
                                debruijn_depth',
                                typerstore,
                                inverse_path',
                                symbolmapstack,
                                source_code_region,
                                per_compile_stuff
                            );
                        };

                    result_generic
                        = 
                        {   result_varhome
                                =
                                vh::make_varhome  make_var;

                            mld::GENERIC {   a_generic_api     =>  spec_api,
                                           typechecked_generic =>  result_typechecked_generic,
                                           varhome             =>  result_varhome,
                                           inlining_data       =>  id::NIL
                                       };
                        };

                    result_declaration
                        = 
                        {   body
                                =
                                ds::PACKAGE_LET
                                  {
                                    declaration => rdec1,

                                    expression
                                        =>
                                        ds::PACKAGE_LET {
                                          declaration => rdec2,
                                          expression  => ds::PACKAGE_BY_NAME result_package
                                        }
                                  };

                            generic_expression
                                =
                                ds::GENERIC_DEFINITION {
                                    parameter       => parameter_package,
                                    parameter_types => param_tps,
                                    definition      => body
                                };

                            ds::GENERIC_DECLARATIONS [
                                ds::NAMED_GENERIC {
                                  name_symbol => generic_name,
                                  a_generic   => result_generic,
                                  definition => generic_expression
                                }
                            ];
                        };


                    ( result_declaration,
                      result_generic
                    );

                };

            pack_generic1 _
                =>
                (ds::SEQUENTIAL_DECLARATIONS [], mld::ERRONEOUS_GENERIC);

        end             #  function pack_generic1 


        #################################################################################
        #
        # fun apply_generic:
        #
        # Match and coerce the argument, then do the generic application.
        # Return the result package, the result typechecked_package expression,
        # and the result abstract syntax declaration of result_package.
        #
        # The argument matching takes place in the Typerstore stored in the
        # generic closure; this is where the parameter_api must be interpreted.
        #
        #################################################################################

        also
        fun apply_generic
            {
              a_generic
                  as
                  mld::GENERIC { a_generic_api   =>  mld::GENERIC_API { parameter_api, body_api, ... },
                            typechecked_generic,
                            ...
                          },

              generic_expression:     mld::Generic_Expression,
              arg_package:            mld::Package,
              arg_expression:         mld::Package_Expression,

              debruijn_depth:         di::Debruijn_Depth,
              symbolmapstack:         syx::Symbolmapstack,
              inverse_path:           ip::Inverse_Path,
              source_code_region:     lnd::Source_Code_Region,

              module_stamp_or_null:   Null_Or( sta::Stamp ),
              stamppath_context:    spc::Context,

              per_compile_stuff
                  as
                  { issue_highcode_codetemp => make_var,
#                   make_fresh_stamp,
                    ...
                  }
                  : trj::Per_Compile_Stuff
            }
            :
            { result_declaration:  ds::Declaration,
              result_package:      mld::Package,
              result_expression:   mld::Package_Expression
            }
                =>
                {   my { generic_closure => mld::GENERIC_CLOSURE { typerstore => generic_typerstore, ... }, ... }
                        =
                        typechecked_generic;

                    if_debugging_say "apply_generic/TOP";



                    # Step #1: match the argument package against parameter_api
                    #
                    my { result_declaration         => arg_declaration1,
                         result_package             => arg_package1,
                         coerced_package_expression => arg_expression1          # Coerced version of supplied package_expression argument.
                        }
                        =
                        thin_package {
                            constraining_api       =>  parameter_api,
                            constrained_package    =>  arg_package,

                            package_expression     =>  arg_expression,
                            typerstore             =>  generic_typerstore,
                            inverse_path           =>  ip::INVERSE_PATH []                 /* ?DAVE XXX BUGGO FIXME */, 

                            module_stamp_or_null,

                            debruijn_depth,
                            symbolmapstack,

                            source_code_region,
                            per_compile_stuff
                        };



                    # ** step #2: do the generic application **

                    typechecked_argument
                        =
                        case arg_package1
                            #
                             mld::A_PACKAGE { typechecked_package, ... } =>   typechecked_package;
                             _                                           =>   mld::bogus_typechecked_package;
                        esac;

                    typechecked_body
                        =
                        expand_generic::expand_generic (

                            typechecked_generic,
                            typechecked_argument,
                            debruijn_depth,
                            stamppath_context,
                            inverse_path,
                            per_compile_stuff
                        );

                    result_package
                        = 
                        {   body_varhome
                                =
                                vh::named_varhome (anonymous_package_symbol, make_var);

                            mld::A_PACKAGE { an_api            => body_api,
                                           typechecked_package => typechecked_body,
                                           varhome             => body_varhome,
                                           inlining_data       => id::NIL
                                         };
                        };

                    result_declaration
                        = 
                        {   parameter_types
                                =
                                gxs::get_packages_typepaths {

                                    an_api                 => parameter_api,
                                    typechecked_package    => typechecked_argument,
                                    typerstore => generic_typerstore,
                                    per_compile_stuff
                                };

                            expression
                                =
                                ds::COMPUTED_PACKAGE {

                                    generic_argument => arg_package1,
                                    a_generic,
                                    parameter_types
                                };

                            result_abs
                                =
                                ds::PACKAGE_LET { declaration => arg_declaration1, expression };


                            ds::PACKAGE_DECLARATIONS
                              [
                                ds::NAMED_PACKAGE
                                  {
                                    name_symbol =>  anonymous_package_symbol,
                                    a_package   =>  result_package,
                                    definition  =>  result_abs
                                  }
                              ];
                        };

                    result_expression
                        =
                        mld::APPLY (generic_expression, arg_expression1);

                    if_debugging_say "apply_generic/BOT";

                    { result_declaration,
                      result_package,
                      result_expression
                    };
                };

            apply_generic { a_generic => mld::ERRONEOUS_GENERIC, ... }
                => 
                { result_declaration =>  ds::PACKAGE_DECLARATIONS [],
                  result_package     =>  mld::ERRONEOUS_PACKAGE, 
                  result_expression  =>  mld::CONSTANT_PACKAGE  mld::bogus_typechecked_package
                };

            apply_generic _
                =>
                bug "apply_generic: bad generic package";

        end;            # fun apply_generic

        # top level wrappers: used for profiling the compilation time 

#       thin_package
#            = 
#           compile_statistics::do_phase (compile_statistics::make_phase "Compiler 034 1-thin_package") thin_package
#
#       match_generic
#            = 
#           compile_statistics::do_phase (compile_statistics::make_phase "Compiler 034 2-match_generic") match_generic
#
#       cast_package
#            = 
#          compile_statistics::do_phase (compile_statistics::make_phase "Compiler 034 3-cast_package") cast_package
#
#       apply_generic
#            = 
#           compile_statistics::do_phase (compile_statistics::make_phase "Compiler 034 4-apply_generic") apply_generic



    };                                                                                                          # package api_match
end;                                                                                                            # stipulate







Comments and suggestions to: bugs@mythryl.org

PreviousUpNext