PreviousUpNext

15.4.653  src/lib/compiler/front/typer/modules/expand-generic-g.pkg

## expand-generic-g.pkg 

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

###       "Within C++, there is a much
###        smaller and cleaner language
###        struggling to get out."
###
###          -- Bjarne Stroustrup


# 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 generic
# expansion stuff.

stipulate
    package di  =  debruijn_index;                                              # debruijn_index                is from   src/lib/compiler/front/typer/basics/debruijn-index.pkg
    package ip  =  inverse_path;                                                # inverse_path                  is from   src/lib/compiler/front/typer-stuff/basics/symbol-path.pkg
    package mld =  module_level_declarations;                                   # module_level_declarations     is from   src/lib/compiler/front/typer-stuff/modules/module-level-declarations.pkg
    package spc =  stamppath_context;                                           # stamppath_context             is from   src/lib/compiler/front/typer-stuff/modules/stamppath-context.pkg
    package trj =  typer_junk;                                                  # typer_junk                    is from   src/lib/compiler/front/typer/main/typer-junk.pkg
herein

    api Expand_Generic {
        #
        package generics_expansion_junk:  Generics_Expansion_Junk;              # Generics_Expansion_Junk       is from   src/lib/compiler/front/typer/modules/generics-expansion-junk-g.pkg

         expand_generic: ( mld::Typechecked_Generic,
                           mld::Typechecked_Package,
                           di::Debruijn_Depth,
                           spc::Context,
                           ip::Inverse_Path,
                           trj::Per_Compile_Stuff
                         )
                        -> mld::Typechecked_Package; 

         debugging:  Ref(  Bool );
    };
end;


#  Genericized to factor out dependencies on highcode: 

stipulate
    package trj =  typer_junk;                                          # typer_junk                    is from   src/lib/compiler/front/typer/main/typer-junk.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 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 sap =  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 stx =  stampmapstack;                                       # stampmapstack                 is from   src/lib/compiler/front/typer-stuff/modules/stampmapstack.pkg
    package tro =  typerstore;                                          # typerstore                    is from   src/lib/compiler/front/typer-stuff/modules/typerstore.pkg
    package tdt =  type_declaration_types;                              # type_declaration_types        is from   src/lib/compiler/front/typer-stuff/types/type-declaration-types.pkg
    #
    include package   module_level_declarations; 
herein 

    generic package   expand_generic_g   (
        #             ================
        #
        package i:  Generics_Expansion_Junk;                            # Generics_Expansion_Junk       is from   src/lib/compiler/front/typer/modules/generics-expansion-junk-g.pkg
    )
    : (weak)  Expand_Generic                                            # Expand_Generic                is from   src/lib/compiler/front/typer/modules/expand-generic-g.pkg
    {
        package generics_expansion_junk = i;

        #  Debugging 
        say = control_print::say;
        debugging = typer_data_controls::expand_generics_g_debugging;

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

        include package   typer_debugging;

        debug_print
            =
            (\\ x => debug_print debugging x; end );     #  Value Restriction 

        fun bug msg
            =
            error_message::impossible ("expand_generic: " + msg);

        anon_generic_sym =   symbol::make_generic_symbol   "anonymous_g";
        param_sym        =   symbol::make_package_symbol "<generic_api_parameter_inst>";
        anon_package_sym =   symbol::make_package_symbol "<anonymous_package>";
        result_id        =   symbol::make_package_symbol "<result_package>";
        return_id        =   symbol::make_package_symbol "<return_package>";

        default_error
            =
            error_message::error_no_file
                (error_message::default_plaint_sink(), REF FALSE)
                (0, 0);

        fun evaluate_type (
                entv,
                typechecked_type_expression,
                typerstore,
                stamppath_context,
                inverse_path, 
                per_compile_stuff as { make_fresh_stamp, ... }: trj::Per_Compile_Stuff
            )
            =
            case typechecked_type_expression
                #
                CONSTANT_TYPE type
                    =>
                    type;

                FORMAL_TYPE (tdt::SUM_TYPE { kind, arity, is_eqtype, namepath, ... } )
                    =>
                    case kind
                        #
                        tdt::SUMTYPE { index=>0, stamps, free_types, family, root=>NULL }
                            =>
                            {   viztyc = mj::translate_type typerstore;
                                nstamps = vector::map  (\\ _ = make_fresh_stamp())  stamps;
                                nst = vector::get (nstamps, 0);
                                nfreetypes = map viztyc free_types;
                                spc::bind_typepath (stamppath_context, nst, entv);

                                tdt::SUM_TYPE
                                  {
                                    stamp => nst,
                                    arity,
                                    is_eqtype,
                                    #
                                    namepath  => ip::append (inverse_path, namepath),
                                    stub      => NULL,
                                    kind      => tdt::SUMTYPE { index    => 0,
                                                               stamps   => nstamps,
                                                               root     => NULL,
                                                               free_types => nfreetypes,
                                                               family
                                                             }
                                };
                            };

                        tdt::SUMTYPE { index=>i, root=>THE rtev, ... }
                            =>
                            {   my (nstamps, nfreetypes, nfamily)
                                    = 
                                    case (tro::find_type_by_module_stamp (typerstore, rtev))
                                        #
                                        tdt::SUM_TYPE { kind => tdt::SUMTYPE dt, ... }
                                            =>
                                            ( dt.stamps,
                                              dt.free_types,
                                              dt.family
                                            );

                                        _ => bug "unexpected case in evaluate_type-FMGENtyc (2)";
                                    esac;

                                nst = vector::get (nstamps, i);         #  "nst" = "new stamp"?

                                spc::bind_typepath (stamppath_context, nst, entv);

                                tdt::SUM_TYPE { stamp     => nst,
                                                arity,
                                                namepath  => ip::append (inverse_path, namepath),
                                                is_eqtype,
                                                stub      => NULL,
                                                kind      => tdt::SUMTYPE { index      =>  i,
                                                                            stamps     =>  nstamps,
                                                                            root       =>  NULL,
                                                                            free_types =>  nfreetypes,
                                                                            family     =>  nfamily
                                                                          }
                                              };
                            };

                        _ => bug "unexpected SUM_TYPE in evaluate_type";
                    esac;


                FORMAL_TYPE (
                     tdt::NAMED_TYPE {
                         stamp,
                         strict,
                         namepath,
                         typescheme => tdt::TYPESCHEME { arity, body }
                     }
                 )
                    =>
                    {   nst = make_fresh_stamp();

                        #  type_identifier=stamp (this should perhaps be more abstract some day) 

                        spc::bind_typepath (stamppath_context, nst, entv);

                        tdt::NAMED_TYPE
                          {
                            stamp      => nst,
                            strict,
                            namepath   => ip::append (inverse_path, namepath),
                            typescheme => tdt::TYPESCHEME { arity, 
                                                            body  => mj::translate_typoid  typerstore  body
                                                          }
                          };
                    };

                TYPEVAR_TYPE stamppath
                    => 
                    {   if_debugging_say (">>evaluate_type[TYPEVAR_TYPE]: " + sap::stamppath_to_string stamppath);

                        tro::find_type_via_stamppath (typerstore, stamppath);
                    };

                 _   => bug "unexpected typechecked_type_expression in evaluate_type";
             esac



        also
        fun evaluate_package_expression (
                package_expression,
                depth,
                stamppath_context,
                module_stamp_v,
                typerstore,
                inverse_path, 
                per_compile_stuff as { make_fresh_stamp, ... }: trj::Per_Compile_Stuff
            )
            =
            {   if_debugging_say ("[Inside evaluate_package_expression ......");
                #
                case package_expression
                    #   
                    VARIABLE_PACKAGE stamppath
                        =>
                        {   if_debugging_say (">>evaluatePackageexpression[VARIABLE_PACKAGE]: " + sap::stamppath_to_string stamppath);

                            (   tro::find_package_via_stamppath (typerstore, stamppath),
                                typerstore
                            );
                        };

                    CONSTANT_PACKAGE typechecked_package
                        =>
                        (typechecked_package, typerstore);

                    PACKAGE { stamp, module_declaration }
                        =>
                        {   stamppath_context = spc::enter_open (stamppath_context, module_stamp_v);
                            #
                            stp = evaluate_stamp_expression (stamp, depth, stamppath_context, typerstore, per_compile_stuff);

                            dictionary = evaluate_declaration( module_declaration, depth, stamppath_context, typerstore, inverse_path, per_compile_stuff);

                            ( { stamp                  =>  stp,
                                typerstore =>  dictionary,

                                property_list          =>  property_list::make_property_list (),
                                stub                   =>  NULL,
                                inverse_path
                              },

                              typerstore
                            );
                        };

                    APPLY (generic_expression, package_expression)
                        =>
                        {   (evaluate_generic (generic_expression, depth, stamppath_context, typerstore, per_compile_stuff))
                                ->
                                (typechecked_generic, typerstore1);

                            my (argument_typechecked_package, typerstore2)
                                = 
                                evaluate_package_expression (
                                  package_expression,
                                  depth,
                                  stamppath_context,
                                  module_stamp_v,
                                  typerstore1,
                                  ip::empty,
                                  per_compile_stuff
                                );

                            stamppath_context
                                =
                                spc::enter_open (stamppath_context, module_stamp_v);

                            ( expand_generic (typechecked_generic, argument_typechecked_package, depth, stamppath_context, inverse_path, per_compile_stuff),
                              typerstore2
                            );
                        };

                    PACKAGE_LET { declaration => module_declaration, expression => package_expression }
                        =>
                        {   typerstore1
                                =
                                evaluate_declaration (
                                  module_declaration,
                                  depth,
                                  stamppath_context,
                                  typerstore,
                                  inverse_path,
                                  per_compile_stuff
                                );

                            my (typechecked_package, typerstore2)
                                = 
                                evaluate_package_expression (
                                  package_expression,
                                  depth,
                                  stamppath_context,
                                  module_stamp_v,
                                  typerstore1, 
                                  inverse_path,
                                  per_compile_stuff
                                );

                            (typechecked_package, typerstore2);
                        };

                    ABSTRACT_PACKAGE (an_api, package_expression)
                        => 
                        {   my (source_typechecked_package, typerstore1)
                                = 
                                evaluate_package_expression
                                  (
                                    package_expression,
                                    depth,
                                    stamppath_context,
                                    module_stamp_v,
                                    typerstore,
                                    inverse_path,
                                    per_compile_stuff
                                  );

                            my {   typechecked_package,
                                    abstract_types,
                                    type_stamppaths
                                }
                                = 
                                i::instantiate_package_abstractions
                                  {
                                    an_api,
                                    typerstore,
                                    source_typechecked_package,
                                    inverse_path, 
                                    source_code_region  => lnd::null_region,
                                    per_compile_stuff
                                  };

                            # Because the abstraction creates a
                            # bunch of new stamps, we have to
                            # bind them to the typechecked_package path context:


                            stamppath_context
                                =
                                spc::enter_open (stamppath_context, module_stamp_v);

                            fun h (tdt::SUM_TYPE gt, ep)
                                    =>
                                    spc::bind_type_long_path (
                                        stamppath_context,
                                        stx::typestamp_of  gt,
                                        ep
                                    );

                                h _ => ();
                            end;

                            paired_lists::apply
                                h
                                ( abstract_types,
                                  type_stamppaths
                                );

                            ( typechecked_package,
                              typerstore1
                            );
                        };

                    COERCED_PACKAGE { boundvar, raw, coercion }
                        =>
                        # Propagage the context inverse_path
                        # into the raw uncoerced package:

                        {   my (raw_typechecked_package, typerstore1)
                                = 
                                evaluate_package_expression
                                  (
                                    raw,
                                    depth,
                                    stamppath_context,
                                    THE boundvar,
                                    typerstore,
                                    inverse_path,
                                    per_compile_stuff
                                  );

                            typerstore2
                                =
                                tro::set (typerstore1, boundvar, PACKAGE_ENTRY raw_typechecked_package);

                            my (typechecked_package, typerstore3)
                                = 
                                evaluate_package_expression
                                  (
                                    coercion,
                                    depth,
                                    stamppath_context,
                                    module_stamp_v, 
                                    typerstore2,
                                    ip::empty,
                                    per_compile_stuff
                                  );

                            (typechecked_package, typerstore3);
                        };

                    FORMAL_PACKAGE _ => bug "unexpected FORMAL_PACKAGE in evaluatePackageexpression";
                esac;
            }


        also
        fun evaluate_generic (
                generic_expression,
                debruijn_depth,
                stamppath_context,
                typerstore, 
                per_compile_stuff as { make_fresh_stamp, ... }: trj::Per_Compile_Stuff
            )
            =
            case generic_expression
                #
                VARIABLE_GENERIC stamppath
                    =>
                    {   if_debugging_say (">>evaluateGeneric[VARIABLE_GENERIC]: " + sap::stamppath_to_string stamppath);

                        (   tro::find_generic_via_stamppath (typerstore, stamppath),
                            typerstore
                        );
                    };

                CONSTANT_GENERIC typechecked_generic
                    =>
                   (typechecked_generic, typerstore);

                LAMBDA { parameter, body }
                    => 
                    {   clos = GENERIC_CLOSURE {   parameter_module_stamp    => parameter,
                                                   body_package_expression => body,
                                                   typerstore
                                               };

                        ( { stamp           => make_fresh_stamp (),
                            generic_closure => clos,
                            property_list   => property_list::make_property_list (),

                            typepath => NULL,
                            inverse_path          => ip::INVERSE_PATH [anon_generic_sym],
                            stub                  => NULL
                          },

                          typerstore
                        );
                    };

                LAMBDA_TP {
                    parameter,
                    body,
                    an_api as GENERIC_API { parameter_api, body_api, ... }
                }
                    =>
                    {   generic_closure
                            =
                            GENERIC_CLOSURE
                              { parameter_module_stamp =>  parameter,
                                body_package_expression         =>  body,
                                typerstore
                              };

                        tps = { inverse_path' = ip::INVERSE_PATH [param_sym];

                                my { typechecked_package => param_typechecked_package,   typepaths => param_tps }
                                    =
                                    i::do_generic_parameter_api {
                                        an_api      => parameter_api,
                                        typerstore, 
                                        inverse_path       => inverse_path',
                                        debruijn_depth,
                                        source_code_region  => lnd::null_region,
                                        per_compile_stuff
                                    };

                                typerstore'
                                    = 
                                    tro::mark (
                                        make_fresh_stamp,
                                        tro::set (typerstore,  parameter,  PACKAGE_ENTRY param_typechecked_package)
                                    );

                                my (body_typechecked_package, _)
                                    = 
                                    evaluate_package_expression (
                                        body,
                                        debruijn_index::next debruijn_depth,
                                        stamppath_context,
                                        NULL,
                                        typerstore',
                                        ip::empty,
                                        per_compile_stuff
                                    );

                                body_tps
                                    = 
                                    i::get_packages_typepaths {
                                        an_api      => body_api,
                                        typechecked_package       => body_typechecked_package, 
                                        typerstore => typerstore',
                                        per_compile_stuff
                                    };

                                tdt::TYPEPATH_GENERIC (param_tps, body_tps);
                              };


                        ( { stamp         => make_fresh_stamp(),
                            generic_closure,
                            property_list => property_list::make_property_list (),

                            typepath => THE tps,
                            inverse_path         => ip::INVERSE_PATH [anon_generic_sym],
                            stub                => NULL
                          },

                          typerstore
                        );
                    };

                LET_GENERIC (module_declaration, generic_expression)
                    =>
                    {   typerstore1
                            =
                            evaluate_declaration
                              (
                                module_declaration,
                                debruijn_depth,
                                stamppath_context,
                                typerstore,
                                ip::empty,
                                per_compile_stuff
                              );

                        my (typechecked_generic, typerstore2)
                            = 
                            evaluate_generic
                              (
                                generic_expression,
                                debruijn_depth,
                                stamppath_context,
                                typerstore1,
                                per_compile_stuff
                              );

                        (typechecked_generic, typerstore2);
                    };

                _ => bug "unexpected cases in evaluateGeneric";
            esac



        also
        fun expand_generic (
                typechecked_generic:                            mld::Typechecked_Generic,
                argument_typechecked_package,
                depth,
                stamppath_context,
                inverse_path,
                per_compile_stuff as { make_fresh_stamp, ... }: trj::Per_Compile_Stuff
            )
            = 
            {   typechecked_generic
                    ->
                    { generic_closure => GENERIC_CLOSURE { parameter_module_stamp, body_package_expression, typerstore },
                     typepath,
                     ...
                    };

                new_typerstore
                    =
                    tro::mark(  make_fresh_stamp,

                               tro::set ( typerstore,
                                         parameter_module_stamp,
                                         PACKAGE_ENTRY argument_typechecked_package
                                       )
                           );

                if_debugging_say ("[Inside EvalAPP] ......");


                case (body_package_expression, typepath)
                    #
                    (   FORMAL_PACKAGE
                            (GENERIC_API { parameter_api, body_api, ... } ),
                            THE tp
                    )
                        => 
                        {   arg_tps
                                =
                                i::get_packages_typepaths
                                  {
                                    an_api                 => parameter_api,
                                    typechecked_package    => argument_typechecked_package,
                                    typerstore,
                                    per_compile_stuff
                                  };

                            result_tp = tdt::TYPEPATH_APPLY (tp, arg_tps);

                            # Failing to add the stamps into the
                            # typechecked_package path context is a
                            # potential bug here. Will fix this in the
                            # future.  XXX BUGGO FIXME ZHONG

###                                                                                     "You can never plan the future by the past." -- Edmund Burke

                            my {   typechecked_package,
                                    abstract_types,
                                    type_stamppaths
                                }
                                =
                                i::macro_expand_formal_generic_body_api
                                  {
                                    an_api           => body_api,
                                    typerstore => new_typerstore,
                                    typepath      => result_tp,
                                    #
                                    inverse_path,
                                    source_code_region     => lnd::null_region,
                                    per_compile_stuff
                                 };

                            fun bind_type (tdt::SUM_TYPE highcode_basetypes, stamppath)
                                    => 
                                    spc::bind_type_long_path (
                                       #
                                       stamppath_context,
                                       stx::typestamp_of  highcode_basetypes,
                                       stamppath
                                    );

                                bind_type _
                                    =>
                                    ();
                            end;


                            paired_lists::apply
                                bind_type
                                (abstract_types, type_stamppaths);

                            typechecked_package;
                        };

                   _
                       => 
                       {   my (typechecked_package, typerstore_additions)
                               =
                               evaluate_package_expression
                                 (
                                   body_package_expression,
                                   depth,
                                   stamppath_context,
                                   NULL,
                                   new_typerstore,
                                   inverse_path,
                                   per_compile_stuff
                                 );

                           # Invariant: macroExpansionDictionaryAdditions should always
                           # be same as newMacroExpansionDictionary if the body of
                           # an generic is always a BasePackage.
                           # Notice that the generic body is constructed
                           # either in the source programs (sml::grm) or in
                           # type-package-language.pkg when dealing
                           # with curried generic applications.


                           typechecked_package;
                       };
                esac;
            }

        also
        fun evaluate_declaration (
                declaration,
                depth,
                stamppath_context,
                typerstore,
                inverse_path,
                per_compile_stuff as { make_fresh_stamp, ... }: trj::Per_Compile_Stuff
            )
            =
            {   if_debugging_say ("[Inside EvalDeclaration ......");
                #
                case declaration
                    #
                    TYPE_DECLARATION (module_stamp, typechecked_type_expression)
                        => 
                        {   typechecked_type
                                = 
                                evaluate_type
                                  ( module_stamp,
                                    typechecked_type_expression,
                                    typerstore,
                                    stamppath_context,
                                    inverse_path,
                                    per_compile_stuff
                                  );

                            tro::set
                              ( typerstore,
                                module_stamp,
                                TYPE_ENTRY typechecked_type
                              );
                        };

                    PACKAGE_DECLARATION (module_stamp, package_expression, symbol)
                        => 
                        {   inverse_path'
                                = 
                                if (  symbol::eq (symbol, return_id)
                                   or symbol::eq (symbol, result_id)
                                   )
                                    inverse_path;
                                else
                                    ip::extend (inverse_path, symbol);
                                fi;

                            my (typechecked_package, typerstore1)
                                =
                                evaluate_package_expression
                                  ( package_expression,
                                    depth,
                                    stamppath_context,
                                    THE module_stamp,
                                    typerstore,
                                    inverse_path',
                                    per_compile_stuff
                                  );

                            tro::set (typerstore1, module_stamp, PACKAGE_ENTRY typechecked_package);
                        };

                    GENERIC_DECLARATION (module_stamp, generic_expression)
                        => 
                        {   (evaluate_generic (generic_expression, depth, stamppath_context, typerstore, per_compile_stuff))
                                ->
                                (typechecked_generic, typerstore1);

                            tro::set (typerstore1, module_stamp, GENERIC_ENTRY typechecked_generic);
                        };

                    SEQUENTIAL_DECLARATIONS decs
                        =>
                        tro::mark (make_fresh_stamp, fold_forward h typerstore decs)
                        where
                            fun h (declaration, typerstore0)
                                = 
                                evaluate_declaration (declaration, depth, stamppath_context, typerstore0, inverse_path, per_compile_stuff);
                        end;

                    # The following may be wrong,
                    # but since ASSERTION! the
                    # bound symbols are all distinct,
                    # it would not appear to cause any harm.

                    LOCAL_DECLARATION (local_declaration, body_declaration)
                        => 
                        {   typerstore1
                                =
                                evaluate_declaration
                                  ( local_declaration,
                                    depth,
                                    stamppath_context,
                                    typerstore,
                                    ip::empty,
                                    per_compile_stuff
                                  );

                            evaluate_declaration (body_declaration, depth, stamppath_context, typerstore1, inverse_path, per_compile_stuff);
                        };

                    _  => typerstore;
                esac;
            }



        also
        fun evaluate_stamp_expression (
                stamp_expression,
                depth,
                stamppath_context,
                typerstore,
                per_compile_stuff as { make_fresh_stamp, ... }: trj::Per_Compile_Stuff
            )
            =
            case stamp_expression
                #
                MAKE_STAMP      => make_fresh_stamp ();

           #    CONST stamp     => stamp; 

                GET_STAMP package_expression
                    =>
                    .stamp (
                        #1 (
                            evaluate_package_expression
                              (
                                package_expression,
                                depth,
                                stamppath_context,
                                NULL,
                                typerstore,
                                ip::empty,
                                per_compile_stuff
                              )
                           )
                    );
            esac;


#       my expandGeneric
#            =
#            compile_statistics::do_phase
#                (compile_statistics::make_phase "Compiler 044 x-expandGeneric")
#                expandGeneric



    };                                                                          # package expand_generic 
end;                                                                            # toplevel stipulate 


## Copyright 1996 by AT&T Bell Laboratories 
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2015,
## released per terms of SMLNJ-COPYRIGHT.


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext