PreviousUpNext

15.4.650  src/lib/compiler/front/typer/main/typer-junk.pkg

## typer-junk.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 for utility functions to build
# deep syntax trees from raw syntax trees.



###                 "Strunk felt that the reader was in serious
###                  trouble most of the time, a man floundering
###                  in a swamp, and that it was the duty of anyone
###                  attempting to write English to drain the swamp
###                  quickly and get his man up on dry ground, or
###                  at least throw him a rope."
###
###                                            -- EB White



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 dsj =  deep_syntax_junk;                    # deep_syntax_junk              is from   src/lib/compiler/front/typer-stuff/deep-syntax/deep-syntax-junk.pkg
    package err =  error_message;                       # error_message                 is from   src/lib/compiler/front/basics/errormsg/error-message.pkg
#   package xet =  eq_types;                            # eq_types                      is from   src/lib/compiler/front/typer/types/eq-types.pkg
    package fis =  find_in_symbolmapstack;              # find_in_symbolmapstack        is from   src/lib/compiler/front/typer-stuff/symbolmapstack/find-in-symbolmapstack.pkg
    package id  =  inlining_data;                       # inlining_data                 is from   src/lib/compiler/front/typer-stuff/basics/inlining-data.pkg
    package lms =  list_mergesort;                      # list_mergesort                is from   src/lib/src/list-mergesort.pkg
    package mj  =  module_junk;                         # module_junk                   is from   src/lib/compiler/front/typer-stuff/modules/module-junk.pkg
    package pds =  prettyprint_deep_syntax;             # prettyprint_deep_syntax       is from   src/lib/compiler/front/typer/print/prettyprint-deep-syntax.pkg
    package pj  =  print_junk;                          # print_junk                    is from   src/lib/compiler/front/basics/print/print-junk.pkg
    package raw =  raw_syntax;                          # raw_syntax                    is from   src/lib/compiler/front/parser/raw-syntax/raw-syntax.pkg
    package rsj =  raw_syntax_junk;                     # raw_syntax_junk               is from   src/lib/compiler/front/parser/raw-syntax/raw-syntax-junk.pkg
    package rwv =  rw_vector;                           # rw_vector                     is from   src/lib/std/src/rw-vector.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 tj  =  type_junk;                           # type_junk                     is from   src/lib/compiler/front/typer-stuff/types/type-junk.pkg
    package mtt =  more_type_types;                     # more_type_types               is from   src/lib/compiler/front/typer/types/more-type-types.pkg
    package tvs =  typevar_set;                         # typevar_set                   is from   src/lib/compiler/front/typer/main/type-variable-set.pkg
    package tdt =  type_declaration_types;              # type_declaration_types        is from   src/lib/compiler/front/typer-stuff/types/type-declaration-types.pkg
    package uds =  unparse_deep_syntax;                 # unparse_deep_syntax           is from   src/lib/compiler/front/typer/print/unparse-deep-syntax.pkg
    package ut  =  unparse_type;                        # unparse_type                  is from   src/lib/compiler/front/typer/print/unparse-type.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
    #
#    include package   print_junk;

herein 

    package   typer_junk
    : (weak)  Typer_Junk                                # Typer_Junk                    is from   src/lib/compiler/front/typer/main/typer-junk.api
    {
        #  Debugging 
        say = control_print::say;
#       debugging = REF FALSE;
        debugging   =   typer_control::typer_junk_debugging;            #  REF FALSE 

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

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

        print_depth = control_print::print_depth;

        prettyprint_declaration         = pds::prettyprint_declaration (syx::empty, NULL);
        prettyprint_expression          = pds::prettyprint_expression  (syx::empty, NULL);
        prettyprint_pattern             = pds::prettyprint_pattern      syx::empty;

        unparse_typoid                  = ut::unparse_typoid                          syx::empty;
        unparse_typevar_ref             = ut::unparse_typevar_ref                     syx::empty;
        unparse_pattern                 = uds::unparse_pattern                  syx::empty;
        unparse_expression              = uds::unparse_expression              (syx::empty, NULL);
        unparse_rule                    = uds::unparse_rule                    (syx::empty, NULL);
        unparse_named_value             = uds::unparse_named_value             (syx::empty, NULL);
        unparse_recursive_named_value   = uds::unparse_recursively_named_value (syx::empty, NULL);

        unparse_declaration
            = 
            (\\ stream
                =
                \\ d
                    =
                    uds::unparse_declaration
                            (syx::empty, NULL)
                            stream
                            (d, *print_depth)
            );

        fun if_debugging_unparse_declaration (msg, declaration)
            =
            if *debugging
                typer_debugging::with_internals
                    (\\ () =  typer_debugging::debug_print debugging (msg, unparse_declaration, declaration));
            fi;

        fun if_debugging_unparse_typoid (msg, type)
            =
            if *debugging
                typer_debugging::with_internals
                    (\\ () =  typer_debugging::debug_print debugging (msg, unparse_typoid, type));
            fi;

        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
                    (\\ () =  typer_debugging::debug_print debugging (msg, unparse_typevar_ref, typevar_ref));
            fi;

        fun if_debugging_unparse_pattern (msg, pattern)
            =
            if *debugging
                typer_debugging::with_internals
                    (\\ () =  typer_debugging::debug_print debugging (msg, unparse_pattern, pattern));
            fi;

        fun if_debugging_unparse_expression (msg, expression)
            =
            if *debugging       
                typer_debugging::with_internals
                    (\\ () =  typer_debugging::debug_print debugging (msg, unparse_expression, expression));
            fi;


        fun if_debugging_prettyprint_expression (msg, expression)
            =
            if *debugging       
                typer_debugging::with_internals
                    (\\ () =  typer_debugging::debug_print debugging (msg, prettyprint_expression, expression));
            fi;

        fun if_debugging_prettyprint_pattern (msg, pattern)
            =
            if *debugging       
                typer_debugging::with_internals
                    (\\ () =  typer_debugging::debug_print debugging (msg, prettyprint_pattern, pattern));
            fi;

        fun if_debugging_prettyprint_declaration (msg, declaration)
            =
            if *debugging       
                typer_debugging::with_internals
                    (\\ () =  typer_debugging::debug_print debugging (msg, prettyprint_declaration, declaration));
            fi;





        fun for' l f
            =
            apply f l;

        fun discard _   =   ();
        fun single x    =   [x];

        internal_sym   =   special_symbols::internal_var_id;


        Syntactic_Typechecking_Context 

            = AT_TOPLEVEL                                       # At top level -- not inside any module, rigid.               
            | IN_PACKAGE                                        # Inside a rigid package, i.e. not inside any generic package body. 
            | IN_API                                            # Within a api body.                                    
            | IN_GENERIC                                        # Inside a generic package.                                           
                { debruijn_depth:       di::Debruijn_Depth,
                  flex:                 sta::Stamp -> Bool      # Predicate recognizing flexible stamps.                      
                };                                              # Nomenclature: "Definition of SML" calls typcons from apis "flexible" an all others "rigid".   


        Per_Compile_Stuff
            =
            per_compile_stuff::Per_Compile_Stuff( ds::Declaration );


        fun new_valvar (s, issue_highcode_codetemp)
            =
            vac::make_ordinary_variable (s, vh::named_varhome (s, issue_highcode_codetemp));

        fun smash f l
            = 
            fold_backward h (NIL, NIL, NIL) l
            where
                fun h (a, (pl, oldl, newl))
                    =
                    {   my (p, old, new) = f a;

                        (   p ! pl,
                            old @ oldl,
                            new @ newl
                        );
                    };
            end;

        stipulate

            fun uniq ((a0 as (a, _, _)) ! (r as (b, _, _) ! _))
                    => 
                    if (sy::eq (a, b) )  uniq r;
                    else                a0 ! uniq r;
                    fi;

                uniq l
                    =>
                    l;
            end;

            fun gtr ((a, _, _), (b, _, _))
                =
                {   a' = sy::name a;
                    b' = sy::name b;

                    a0 = string::get_byte_as_char (a', 0);
                    b0 = string::get_byte_as_char (b', 0);

                    if   (char::is_digit a0)
                        
                         if   (char::is_digit b0   )   size a' > size b' or size a' == size b' and a' > b';
                         else                          FALSE;                                           fi;
                    else
                         if   (char::is_digit b0   )   TRUE;
                         else                          (a' > b');                fi;
                    fi;
                };

        herein

            fun sort3 x
                =
                uniq (lms::sort_list gtr x);
        end;

        equalsym        =   sy::make_value_symbol "=";
        anon_param_name =   sy::make_package_symbol "<AnonParam>";

        #  following could go in deep_syntax 

        bogus_id      =   sy::make_value_symbol "*bogus*";
        bogus_exn_id  =   sy::make_value_symbol "*Bogus*";


        truepat    =   ds::CONSTRUCTOR_PATTERN        (           mtt::true_valcon,                     [] );
        trueexp    =   ds::VALCON_IN_EXPRESSION       { valcon => mtt::true_valcon,  typescheme_args => [] };

        falsepat   =   ds::CONSTRUCTOR_PATTERN        (           mtt::false_valcon,                    [] );
        falseexp   =   ds::VALCON_IN_EXPRESSION       { valcon => mtt::false_valcon, typescheme_args => [] };

        nilpat     =   ds::CONSTRUCTOR_PATTERN        (           mtt::nil_valcon,                      [] );
        nilexp     =   ds::VALCON_IN_EXPRESSION       { valcon => mtt::nil_valcon,   typescheme_args => [] };

        conspat    =   \\ pattern = ds::APPLY_PATTERN (           mtt::cons_valcon,                     [], pattern );
        consexp    =   ds::VALCON_IN_EXPRESSION       { valcon => mtt::cons_valcon,  typescheme_args => [] };

        void_expression
            =
            dsj::void_expression;

        void_pattern
            =
            ds::RECORD_PATTERN
              {
                fields        =>  NIL,
                is_incomplete =>  FALSE,
                type_ref      =>  REF tdt::UNDEFINED_TYPOID
              };

        bogus_expression
            =
            ds::VARIABLE_IN_EXPRESSION
              {
                var             =>  REF (vac::make_ordinary_variable (bogus_id, vh::null_varhome)),
                typescheme_args =>      []
              };



        #  Verify that all the elements of a list are unique,    
        #  By sorting and then equality-checking adjacent pairs: 
        #
        fun forbid_duplicates_in_list (err, message, names)
            =
            f names'
            where
                names' = lms::sort_list sy::symbol_gt names;

                fun f (x ! y ! rest)
                        =>
                        {   if (sy::eq (x, y))   err err::ERROR (message + ": " + sy::name x) err::null_error_body;   fi;
                            f (y ! rest);
                        };

                   f _ => ();
                end;
            end;

        # Extract all the variable namings from a pattern,
        # and return as a new Symbolmapstack.
        #
        # NOTE: the "free_or_vars" function in
        # type-core-language.pkg should
        # probably be merged with this.        XXX BUGGO FIXME
        #
        fun bind_varp (patlist, err)
            =
            {   vl = REF (NIL: List( sy::Symbol ));
                #
                symbolmapstack = REF (syx::empty: syx::Symbolmapstack);

                fun f (ds::VARIABLE_IN_PATTERN (v as vac::PLAIN_VARIABLE { path => syp::SYMBOL_PATH [name], inlining_data, ... } ))
                        => 
                        {   if (sy::eq (name, equalsym))            #  Major hack XXX BUGGO FIXME 
                                # if id::is_baseop_info (id::fromExn inlining_data) then ()
                                # else
                                err  err::WARNING  "renaming ="  err::null_error_body;
                            fi;

                            symbolmapstack := syx::bind (name, sxe::NAMED_VARIABLE v, *symbolmapstack); 

                            vl := name ! *vl;
                       };

                   f (ds::RECORD_PATTERN { fields, ... } )      =>  apply (\\(_, pattern)=>f pattern; end ) fields;
                   f (ds::VECTOR_PATTERN (patterns, _))         =>  apply f patterns;
                   f (ds::APPLY_PATTERN (_, _, pattern))        =>  f pattern;
                   f (ds::TYPE_CONSTRAINT_PATTERN (pattern, _)) =>  f pattern;
                   f (ds::AS_PATTERN (p1, p2))                  =>  { f p1; f p2;};
                   f (ds::OR_PATTERN (p1, p2))                  =>  { f p1; bind_varp([p2], err); ();};
                   f _ => ();
               end;

               apply f patlist;

               forbid_duplicates_in_list (err, "duplicate variable in pattern (s)", *vl);

               *symbolmapstack;
            };


#       fun isPrimPattern (ds::VARIABLE_IN_PATTERN { info, ... } ) = ii::is_baseop_info (info)
#         | isPrimPattern (ds::COSTRAINTpat (ds::VARIABLE_IN_PATTERN { info, ... }, _)) = ii::is_baseop_info (info)
#         | isPrimPattern _ = FALSE;


        # replace_pattern_variables:
        #   "alpha convert" a pattern, replacing old variables by
        #   new ones, with new HIGHCODE_VARIABLE varhomees.
        #   Returns the converted pattern, the list of old variables (VARpats)
        #   and the list of new variables (VALvars).
        # called only once, in typecheckValueNaming in elabcore.sml

        fun replace_pattern_variables (prettyprint, per_compile_stuff as { issue_highcode_codetemp, ... } : Per_Compile_Stuff)
            =
            {   my oldnew:  Ref( List( (ds::Case_Pattern, vac::Variable) ) )
                           = REF NIL;

                fun f (p as ds::VARIABLE_IN_PATTERN (vac::PLAIN_VARIABLE { varhome => acc, inlining_data, vartypoid_ref => REF type', path } ))
                        =>
                        {   fun find ((ds::VARIABLE_IN_PATTERN (vac::PLAIN_VARIABLE { varhome => acc', ... } ), x) ! rest, v)
                                    => 
                                    case (vh::highcode_variable_or_null  acc')            #  David B MacQueen: can this return NULL? XXX BUGGO FIXME 
                                        #
                                        THE w
                                            =>
                                            if   (v == w)   x;
                                            else            find (rest, v);
                                            fi;

                                                  # David B MacQueen:  Can the TRUE branch happen?      XXX BUGGO FIXME
                                                  # ie. two variables with same highcode_variable
                                                  # in a pattern?

                                        _ => find (rest, v);
                                    esac;


                                find (_ ! rest, v)
                                    =>
                                    find    (rest, v);

                                find (NIL, v)            #  David B MacQueen: assert this rule always applies ? XXX FIXME BUGGO 
                                    =>                      
                                    {   x = vac::PLAIN_VARIABLE
                                              {
                                                varhome        => vh::duplicate_varhome (v, issue_highcode_codetemp),
                                                inlining_data,
                                                #
                                                vartypoid_ref      => REF type',
                                                path
                                              };

                                        oldnew := (p, x) ! *oldnew;

                                        x;
                                    };
                            end;

                            case (vh::highcode_variable_or_null  acc)
                                #
                                THE v =>   ds::VARIABLE_IN_PATTERN (find (*oldnew, v));
                                _     =>   bug "unexpected varhome in replace_pattern_variables";
                            esac;

                        };

                    f (ds::RECORD_PATTERN { fields, is_incomplete, type_ref } )
                        =>
                        ds::RECORD_PATTERN {

                            fields  => map   (\\ (l, p)  =>  (l, f p); end )   fields,
                            is_incomplete,
                            type_ref
                        };

                    f (ds::VECTOR_PATTERN (patterns, t))   =>   ds::VECTOR_PATTERN (map f patterns,  t);
                    f (ds::APPLY_PATTERN (d, c, p))        =>   ds::APPLY_PATTERN (d, c, f p);
                    f (ds::OR_PATTERN (a, b))              =>   ds::OR_PATTERN (f a, f b);
                    f (ds::TYPE_CONSTRAINT_PATTERN (p, t)) =>   ds::TYPE_CONSTRAINT_PATTERN (f p, t);
                    f (ds::AS_PATTERN (p, q))              =>   ds::AS_PATTERN (f p, f q);
                    f p => p;
                end;

                np   =   f prettyprint;

                fun h ((a, b) ! r, x, y)   =>   h (r, a ! x, b ! y);
                    h (      [], x, y)   =>   (np, x, y);
                end;


                h (*oldnew, [], []);
            };



        # Sort the labels in a record.
        # The order is redefined to take
        # the usual ordering on numbers
        # expressed by strings (tuples):
        #
        stipulate 

            fun sort x
                = 
                lms::sort_list
                    (   \\ ((a, _), (b, _))
                           =>
                           tj::label_is_greater_than (a, b); end 
                    )
                    x;
        herein
            fun sort_record (l, err)
                =
                {   forbid_duplicates_in_list (err, "duplicate label in record", map #1 l);
                    sort l;
                };
        end;


        fun make_record_expression (fields, err)
            =
            ds::RECORD_IN_EXPRESSION (f (0, fields'))
            where
                fields' =   map (\\ (id, expression) = (id, (expression, REF 0)))
                                fields;

                fun assign (i,   (_, (_, r))  !  tl)
                        =>
                        {   r := i;
                            assign (i+1, tl);
                        };

                    assign (_, NIL)
                        =>
                        ();
                end;


                fun f (i, (id, (expression, REF n)) ! rest)
                        =>
                        ( ds::NUMBERED_LABEL {  name => id,   number => n },
                          expression
                        )
                        !
                        f (i+1, rest);

                    f (_, NIL)
                        =>
                        NIL;
                end;

                assign (0, sort_record (fields', err));
            end;

        tupleexp   =   dsj::tupleexp;

        /*
        fun TUPLE_IN_EXPRESSION l
            = 
            {   fun addlabels (i, e ! r) = 
                      (LABEL { number=i - 1, name=(tuples::number_to_label i) }, e) 
                       ! addlabels (i+1, r)
                  | addlabels(_, NIL) = NIL;
             
                ds::RECORD_IN_EXPRESSION (addlabels (1, l));
            }
        */

        fun tpselexp (e, i)
            = 
            {   lab = ds::NUMBERED_LABEL {
                          number => i - 1,
                          name   => (tuples::number_to_label i)
                      };

                ds::RECORD_SELECTOR_EXPRESSION (lab, e);
            };

        # Adds a default case to a list of rules. 
        # If given list is marked, all ordinarily-marked expressions 
        #   in default case are also marked, using end of given list 
        #   as location.
        #
        # KLUDGE! The debugger distinguishes marks in the default case by
        #   the fact that start and end locations for these marks 
        #   are the same!
        #
        fun complete_match'' rule [ r as ds::CASE_RULE ( pattern, ds::SOURCE_CODE_REGION_FOR_EXPRESSION (_, (_, right))) ]
                =>
                [ r, rule (\\ expression => ds::SOURCE_CODE_REGION_FOR_EXPRESSION (expression, (right, right)); end ) ];

            complete_match'' rule [r as ds::CASE_RULE (pattern, ds::TYPE_CONSTRAINT_EXPRESSION (ds::SOURCE_CODE_REGION_FOR_EXPRESSION (_, (_, right)), _)) ]
                =>
                [ r, rule (\\ expression => ds::SOURCE_CODE_REGION_FOR_EXPRESSION (expression, (right, right)); end ) ];

            complete_match'' rule [r]
                =>
                [ r, rule (\\ expression = expression) ];

            complete_match'' rule (a ! r)
                =>
                a ! complete_match'' rule r;

            complete_match'' _ _
                =>
                bug "completeMatch''";
        end;


        fun complete_match' (ds::CASE_RULE (p, e))
            =
            complete_match'' (\\ marker =  ds::CASE_RULE (p, marker e));


        fun complete_match (symbolmapstack, name)
            =
            complete_match'' 
                (   \\ marker
                       =
                       ds::CASE_RULE (
                           ds::WILDCARD_PATTERN, 
                           marker (
                               ds::RAISE_EXPRESSION (
                                   ds::VALCON_IN_EXPRESSION {
                                     valcon          =>  core_access::get_exception (symbolmapstack, name),
                                     typescheme_args =>  []
                                   },
                                   tdt::UNDEFINED_TYPOID
                               )
                           )
                       )
                );

        trivial_complete_match   =   complete_match (syx::empty, "MATCH");

        tuplepat   =   dsj::tuplepat;

        /*
        fun TUPLEPAT l
            =
            {   fun addlabels (i, e ! r) = (tuples::number_to_label i, e) ! addlabels (i+1, r)
                  | addlabels(_, NIL) = NIL;

                RECORD_PATTERN { fields => addlabels (1, l), is_incomplete => FALSE, type_ref => REF tdt::UNDEFINED_TYPOID };
            }
        */

        fun wrap_recdec (rvbs, per_compile_stuff as { issue_highcode_codetemp, ... } : Per_Compile_Stuff)
            = 
            {   fun g (   ds::NAMED_RECURSIVE_VALUE {

                              variable => v
                                         as
                                         vac::PLAIN_VARIABLE {
                                             path => syp::SYMBOL_PATH [ symbol ],
                                             ...
                                         },
                              ...
                          },
                          nvars
                      )
                        => 
                        {   nv = new_valvar (symbol, issue_highcode_codetemp);

                            ( (v, nv, symbol)   !   nvars);
                        };

                    g _
                        =>
                        bug "wrapRECdecGen: NAMED_RECURSIVE_VALUE";
                end;

                vars   =   fold_backward g [] rvbs;

                odec   =   ds::RECURSIVE_VALUE_DECLARATIONS  rvbs;

                raw_typevars
                    = 
                    case rvbs
                        #                     
                        (ds::NAMED_RECURSIVE_VALUE { raw_typevars, ... } ) ! _
                            =>
                            raw_typevars;

                        _   =>   bug "unexpected empty rvbs list in wrap_recdec";
                    esac;


                declarations
                    =
                    case vars
                        #                     
                        [ (v, nv, symbol) ]
                            =>
                            ds::VALUE_DECLARATIONS [
                                #
                                ds::VALUE_NAMING
                                  {
                                    pattern              =>  ds::VARIABLE_IN_PATTERN nv,
                                    expression           =>  ds::LET_EXPRESSION (odec, ds::VARIABLE_IN_EXPRESSION {  var => REF v,  typescheme_args => []  }),
                                    raw_typevars,
                                    generalized_typevars =>  []
                                  }
                            ];


                         _
                            => 
                            {   vs = map (   \\ (v, _, _)
                                                =
                                                ds::VARIABLE_IN_EXPRESSION {  var => REF v,  typescheme_args => []  }
                                         )
                                         vars;

                                rootv = new_valvar (internal_sym, issue_highcode_codetemp);

                                rvexp = ds::VARIABLE_IN_EXPRESSION {  var => REF rootv,  typescheme_args => []  };

                                nvdec = ds::VALUE_DECLARATIONS
                                          [
                                            ds::VALUE_NAMING
                                              {
                                                pattern            =>  ds::VARIABLE_IN_PATTERN rootv,
                                                expression         =>  ds::LET_EXPRESSION (odec, tupleexp vs),
                                                raw_typevars,
                                                generalized_typevars =>  []
                                              }
                                          ];

                                h (vars, 1, [])
                                where
                                    fun h ([], _, d)
                                            =>  
                                            ds::LOCAL_DECLARATIONS (nvdec, ds::SEQUENTIAL_DECLARATIONS (reverse d));

                                        h ((_, nv, _) ! r, i, d)
                                            => 
                                            {   nvb =  ds::VALUE_NAMING
                                                         {
                                                           pattern            =>  ds::VARIABLE_IN_PATTERN  nv,
                                                           expression         =>  tpselexp (rvexp, i),
                                                           raw_typevars   =>  REF [],
                                                           generalized_typevars =>  []
                                                         };

                                                h   (r,   i + 1,   ds::VALUE_DECLARATIONS ([ nvb ]) ! d);
                                            };
                                    end;
                                end;

                            };
                    esac;


                ( vars, 
                  declarations
                );
            };

# Commented out 2009-04-21 CrT because it is never referenced:
#
#       fun wrap_named_recursive_values_list0 (rvbs, per_compile_stuff)
#           = 
#           {   my   (vars, ndec)   =   wrap_recdec (rvbs, per_compile_stuff);
#
#               case vars
#                 
#                    [(_, nv, _)]   =>   (nv, ndec);
#                    _              =>   bug "unexpected case in wrapRecursiveValueNamingsList0";
#                esac;
#           };

        # This gets called once locally (below) and once from
        #
        #     src/lib/compiler/front/typer/main/type-core-language.pkg
        #
        fun wrap_named_recursive_values_list (rvbs, per_compile_stuff)
            = 
            {   (wrap_recdec (rvbs, per_compile_stuff))
                    ->
                    (vars, new_declaration);

                fun h ((v, nv, symbol), symbolmapstack)
                    =
                    syx::bind (symbol, sxe::NAMED_VARIABLE nv, symbolmapstack);

                new_symbolmapstack
                    =
                    fold_forward h syx::empty vars;

                ( new_declaration,
                  new_symbolmapstack
                );
            };

        arg_var_sym   =   sy::make_value_symbol "arg";

        fun c_markexp (e, r)
            =
            if (*typer_control::mark_deep_syntax_tree)   ds::SOURCE_CODE_REGION_FOR_EXPRESSION (e, r);
            else                                         e;
            fi;

        fun make_deep_syntax_for_mutually_recursive_functions
            ( complete_match,
              named_function_list,
              per_compile_stuff as   {   issue_highcode_codetemp,   error_match,   ...   }: Per_Compile_Stuff
            )
            = 
            wrap_named_recursive_values_list (

                map named_function_to_named_recursive_values
                    named_function_list,

                per_compile_stuff
            )
            where
                fun named_function_to_named_recursive_values
                      { var,
                        clauses as (   { deep_syntax_patterns, result_typoid, deep_syntax_expression }   !   _),
                        raw_typevars,
                        source_code_region
                      }
                        =>
                        {   fun getvar _
                                =
                                new_valvar (arg_var_sym, issue_highcode_codetemp);

                            vars   =   map getvar deep_syntax_patterns;

                            fun not1 (f,[a]) =>   a;
                                not1 (f,  l) =>   f l;
                            end;

                            fun do_var valvar
                                =
                                ds::VARIABLE_IN_EXPRESSION {  var => REF valvar,  typescheme_args => []  };


                            fun do_clause ( { deep_syntax_patterns, deep_syntax_expression, result_typoid=>NULL } )
                                    =>
                                    ds::CASE_RULE   (not1 (tuplepat, deep_syntax_patterns),   deep_syntax_expression);

                                do_clause ( { deep_syntax_patterns, deep_syntax_expression, result_typoid=>THE typoid } )
                                    =>
                                    ds::CASE_RULE (   not1 (tuplepat, deep_syntax_patterns),
                                                  ds::TYPE_CONSTRAINT_EXPRESSION (deep_syntax_expression, typoid)
                                              );
                            end;

    #      -- Matthias says: this seems to generate slightly bogus marks:            XXX BUGGO FIXME
    #    
    #                   mark =  case (hd clauses, list::last clauses)
    #
    #                                 of (   { expression=ds::SOURCE_CODE_REGION_FOR_EXPRESSION(_, (a, _)), ... },
    #                                        { expression=ds::SOURCE_CODE_REGION_FOR_EXPRESSION(_, (_, b)), ... }
    #                                         )
    #                                         =>
    #                                    (\\ e => ds::SOURCE_CODE_REGION_FOR_EXPRESSION (e, (a, b)))
    #
    #                                  | _ => \\ e => e

                            fun make_expression [var]
                                    => 
                                    ds::FN_EXPRESSION (complete_match (map do_clause clauses), tdt::UNDEFINED_TYPOID);

                                make_expression vars
                                    => 
                                    fold_backward
                                        (   \\ (w, e)
                                               =
                                               ds::FN_EXPRESSION (
                                                   complete_match
                                                       [   ds::CASE_RULE (ds::VARIABLE_IN_PATTERN w,   /*mark*/ e)   ],
                                                       tdt::UNDEFINED_TYPOID
                                               )
                                        )
                                        (   ds::CASE_EXPRESSION (
                                                tupleexp (map do_var vars),
                                                complete_match (map do_clause clauses),
                                                TRUE
                                            )
                                        )
                                        vars;
                            end;

                            ds::NAMED_RECURSIVE_VALUE
                              {
                                variable           =>  var,
                                expression         =>  c_markexp (make_expression vars, source_code_region),
                                raw_typevars,
                                generalized_typevars =>  [],
                                null_or_type       =>  NULL
                              };
                        };

                    named_function_to_named_recursive_values _
                        =>
                        bug "make_deep_syntax_for_mutually_recursive_functions";
                end;
            end;                                                        # fun make_deep_syntax_for_mutually_recursive_functions

        fun make_handle_expression (
                expression,
                rules,
                per_compile_stuff as { issue_highcode_codetemp, ... }: Per_Compile_Stuff
            )
            =
            {   v     =  new_valvar (rsj::exception_id, issue_highcode_codetemp);
                r     =  ds::CASE_RULE  (ds::VARIABLE_IN_PATTERN v,  ds::RAISE_EXPRESSION (ds::VARIABLE_IN_EXPRESSION { var => REF v, typescheme_args => [] },  tdt::UNDEFINED_TYPOID));
                rules =  complete_match' r rules;
                #
                ds::EXCEPT_EXPRESSION (expression, (rules, tdt::UNDEFINED_TYPOID));
            };



        # Transform a raw-syntax var_pattern
        # into either a deep-syntax variable
        # or a deep-syntax constructor.
        #
        # If we are given a long path (>1)
        # then it has to be a constructor:
        #
        fun do_var_pattern ( spath,
                             symbolmapstack,
                             err,
                             per_compile_stuff as { issue_highcode_codetemp, ... }: Per_Compile_Stuff
            )
            = 
            case spath
                #             
                symbol_path::SYMBOL_PATH [id]
                    =>
                    case (fis::find_value_by_symbol   (symbolmapstack,   id,   \\ _ = raise exception syx::UNBOUND))
                        #
                        vac::CONSTRUCTOR c
                            =>
                            ds::CONSTRUCTOR_PATTERN (c,[]); 

                        _
                            =>
                            ds::VARIABLE_IN_PATTERN (new_valvar (id, issue_highcode_codetemp));
                    esac
                    except
                        syx::UNBOUND
                        =
                        {   name = symbol::name id;

                            if   (string::has_upper name)

                                 err err::ERROR 
                                     (   "Undefined constructor: "
                                     +   name
                                     )
                                     err::null_error_body;
                            fi;

# XXX PLUGH
# print ("src/lib/compiler/front/typer/main/typer-junk.pkg/do_var_pattern: symbol::name(id) = '" + (symbol::name id) + "'\n");
                            ds::VARIABLE_IN_PATTERN (new_valvar (id, issue_highcode_codetemp));

                        };


                _
                    =>
                    ds::CONSTRUCTOR_PATTERN 
                        #
                        case (fis::find_value_via_symbol_path (symbolmapstack, spath, err))
                            #
                            vac::VARIABLE c
                                =>
                                {   err err::ERROR 
                                        (   "variable found where constructor is required: "
                                        +   symbol_path::to_string spath
                                        )
                                        err::null_error_body;

                                    (vac::bogus_valcon, []);
                                };

                            vac::CONSTRUCTOR c
                                =>
                                (c, []);
                        esac
                        except
                            syx::UNBOUND
                            =
                            bug "unbound untrapped";

            esac;


        fun make_record_pattern (l, is_incomplete, err)
            =
            ds::RECORD_PATTERN
              {
                fields   =>  sort_record (l, err),
                type_ref =>  REF tdt::UNDEFINED_TYPOID,
                is_incomplete
              };


        fun clean_pattern
                err 
                (ds::CONSTRUCTOR_PATTERN (tdt::VALCON { is_constant => FALSE, name, ... }, _ ))
                => 
                {   err
                        err::ERROR
                        (   "data constructor "
                        +   sy::name name
                        +   " used without argument in pattern"
                        )
                        err::null_error_body;

                    ds::WILDCARD_PATTERN;
                };

            clean_pattern
                err
                (p as ds::CONSTRUCTOR_PATTERN (tdt::VALCON { is_lazy => TRUE, ... }, _ ))
                => 
                ds::APPLY_PATTERN (
                    mtt::dollar_valcon,
                    [],
                    p
                );                #  LAZY   # second argument = NIL OK? 

            clean_pattern err p
                =>
                p;
        end;

        fun pattern_to_string ds::WILDCARD_PATTERN => "_";
            #
            pattern_to_string (ds::VARIABLE_IN_PATTERN (vac::PLAIN_VARIABLE  { path, ... }   ))  =>  syp::to_string path;
            pattern_to_string (ds::CONSTRUCTOR_PATTERN (tdt::VALCON { name, ... }, _))  =>  sy::name name;

            pattern_to_string (ds::INT_CONSTANT_IN_PATTERN (i, _)) => multiword_int::to_string i;

            pattern_to_string (ds::FLOAT_CONSTANT_IN_PATTERN  s)   =>   s;
            pattern_to_string (ds::STRING_CONSTANT_IN_PATTERN s)   =>   s;
            pattern_to_string (ds::CHAR_CONSTANT_IN_PATTERN   s)   =>   "'" + s + "'";

            pattern_to_string (ds::RECORD_PATTERN _)   =>   "<record>";
            pattern_to_string (ds::APPLY_PATTERN    _)   =>   "<application>";

            pattern_to_string (ds::TYPE_CONSTRAINT_PATTERN _)   =>   "<constraint pattern>";
            pattern_to_string (ds::AS_PATTERN    _)   =>   "<layered pattern>";

            pattern_to_string (ds::VECTOR_PATTERN     _)   =>   "<vector pattern>";
            pattern_to_string (ds::OR_PATTERN         _)   =>   "<or pattern>";

            pattern_to_string _ => "<illegal pattern>";
        end;

        fun make_apply_pattern err (ds::CONSTRUCTOR_PATTERN (d as tdt::VALCON { is_constant=>FALSE, is_lazy, ... }, t), p)
                =>
                {   p1 =  ds::APPLY_PATTERN (d, t, p);
                    #
                    if is_lazy   ds::APPLY_PATTERN (mtt::dollar_valcon, [], p1);
                    else         p1;
                    fi;
                };

            make_apply_pattern err (ds::CONSTRUCTOR_PATTERN (d as tdt::VALCON { name, ... }, _), _)
                => 
                {   err
                        err::ERROR
                        (   "constant constructor applied to argument in pattern:"
                        +   sy::name name
                        )
                        err::null_error_body;

                    ds::WILDCARD_PATTERN;
                };

            make_apply_pattern err (operator, _)
                => 
                {   err
                        err::ERROR
                        (
                            cat [
                               "non-constructor applied to argument in pattern: ",
                               pattern_to_string operator
                            ]
                        )
                        err::null_error_body;

                    ds::WILDCARD_PATTERN;
                };
        end;

        fun make_layered_pattern ((x as ds::VARIABLE_IN_PATTERN _), y, _)
                =>
                ds::AS_PATTERN (x, y);

            make_layered_pattern (ds::TYPE_CONSTRAINT_PATTERN (x, t), y, err)
                => 
                make_layered_pattern (x, ds::TYPE_CONSTRAINT_PATTERN (y, t), err);

            make_layered_pattern (x, y, err)
                =>
                {   err err::ERROR "pattern to left of \"as\" must be variable" err::null_error_body;
                    y;
                };
        end;

        fun calculate_strictness (arity, body)
            =
            {   argument_found =   rwv::make_rw_vector (arity, FALSE);

                fun search (tdt::TYPEVAR_REF { id, ref_typevar => REF (tdt::RESOLVED_TYPEVAR type) } )  =>  search type;
                    search (tdt::TYPESCHEME_ARG n)                                                      =>  rwv::set (argument_found, n, TRUE);
                    #
                    search (tdt::TYPCON_TYPOID (typ, args))                                             =>  apply search args;
                    search _                                                                            =>  ();                  #  for now... 
                end;

                search body;

                rwv::fold_backward   (!)   NIL   argument_found;
            };



        # Check whether the
        # type variables appearing in a type
        # (used) are bound (as parameters in
        # a type declaration):
        #
        fun check_bound_typevars (used, bound, err)
            =
            {   boundset
                    = 
                    fold_backward
                        (   \\ (v, s)
                               =
                               tvs::union (tvs::singleton v, s, err)
                        )
                        tvs::empty
                        bound;

                apply nasty (tvs::get_elements (tvs::diff (used, boundset, err)))
                where
                    fun nasty { id => _, ref_typevar => REF (tdt::RESOLVED_TYPEVAR (tdt::TYPEVAR_REF (typevar_ref as { id, ref_typevar }) )) }
                            =>
                            nasty  typevar_ref;

                        nasty (typevar_ref as { id => _, ref_typevar => (user_bound as REF (tdt::USER_TYPEVAR _)) })
                            => 
                            err
                                err::ERROR
                                (   "Unbound type variable in type declaration: "
                                +    ut::typevar_ref_printname  typevar_ref
                                )
                                err::null_error_body;

                        nasty _
                            =>
                            bug "check_bound_typevars";
                    end;
                end;

            };



        #
        fun symbol_naming_label
            ( (ds::NUMBERED_LABEL { name, ... }):  ds::Numbered_Label
            )
            : symbol::Symbol
            =
            name;

        exception IS_RECURSIVE;



        # Convert a deep syntax ds::NAMED_RECURSIVE_VALUE
        # expression to a deep syntax ds::VALUE_DECLARATIONS
        # if we can and a deep syntax ds::RECURSIVE_VALUE_DECLARATIONS
        # if we must.
        #
        # This was formerly done in
        #     src/lib/compiler/back/top/translate/nonrec.pkg;
        # but is now done during type checking -- our sole
        # call is currently in
        #    src/lib/compiler/front/typer/types/type-core-language-declaration-g.pkg
        #
        fun convert_deep_syntax_named_recursive_values_list_to_deep_syntax_value_declarations_or_recursive_value_declarations
                (   rvbs
                    as
                    [   ds::NAMED_RECURSIVE_VALUE
                          {
                            variable as  vac::PLAIN_VARIABLE {
                                           varhome =>  vh::HIGHCODE_VARIABLE  our_root_variable,
                                           ...
                                         }, 
                            expression,
                            null_or_type,
                            raw_typevars,
                            generalized_typevars
                          }
                    ]
                )
                => 
                {
                    {
                                                                                                                                # If 'expression' contains an internal
                                                                                                                                # reference to 'our_root_variable'
                                                                                                                                # from above then we must build
                                                                                                                                # a RECURSIVE_VALUE_DECLARATIONS
                                                                                                                                # return value, but otherwise we
                                                                                                                                # can get away with a simple
                                                                                                                                # VALUE_DECLARATIONS return value. 
                                                                                                                                #
                                                                                                                                # Here we recursively dagwalk
                                                                                                                                # 'expression' searching for appearances
                                                                                                                                # of our_root_variable.  If we find one
                                                                                                                                # we raise IS_RECURSIVE and exit via the
                                                                                                                                # below 'except' clause, otherwise we
                                                                                                                                # return the below VALUE_DECLARATIONS
                                                                                                                                # expression:
                                                                                                                                #
                        check_exp expression;
                        #
                        pattern    =  ds::VARIABLE_IN_PATTERN variable;
                        expression =  case null_or_type
                                           THE type =>  ds::TYPE_CONSTRAINT_EXPRESSION (expression, type);
                                           NULL     =>  expression;
                                      esac;
                        #
                                                                                                                                if (*debugging and ((list::length generalized_typevars) > 0))
                                                                                                                                    printf "Creating NAMED_VALUE from NAMED_RECURSIVE_VALUE with %d-entry generalized_typevars list in \
                                                                                                                                                \convert_deep_syntax_named_recursive_values_list_to_deep_syntax_value_declarations_or_recursive_value_declarations in typer-junk.pkg\n" (list::length generalized_typevars);
                                                                                                                                    printf "\nNAMED_VALUE.generalized_typevars: (%d)\n" (list::length generalized_typevars);
                                                                                                                                    apply  unparse_typevar_ref  generalized_typevars
                                                                                                                                    where
                                                                                                                                        fun unparse_typevar_ref  typevar_ref
                                                                                                                                            =
                                                                                                                                            if_debugging_unparse_typevar_ref ("", typevar_ref);
                                                                                                                                    end;
                                                                                                                                    printf "\n";
                                                                                                                                    if_debugging_unparse_pattern    ("\nNAMED_VALUE.pattern == \n", (pattern,100));
                                                                                                                                    if_debugging_unparse_expression ("\nNAMED_VALUE.expression == \n", (expression,100));
                                                                                                                                    if_debugging_prettyprint_pattern    ("\nNAMED_VALUE.pattern    prettyprint == \n", (pattern,   100));
                                                                                                                                    if_debugging_prettyprint_expression ("\nNAMED_VALUE.expression prettyprint == \n", (expression,100));
                                                                                                                                fi;

                        ds::VALUE_DECLARATIONS
                          [
                            ds::VALUE_NAMING
                              {
                                pattern,
                                expression,
                                raw_typevars,
                                generalized_typevars
                              }
                          ];
                    }
                    except
                        IS_RECURSIVE   =   ds::RECURSIVE_VALUE_DECLARATIONS  rvbs;
                }
                where

                    # All we do here is raise IS_RECURSIVE
                    # if 'e' anywhere contains 'our_root_variable':
                    #
                    fun check_exp e                                     # 'e' == 'exp' == 'expression'
                        =
                        case e
                            #
                            ds::VARIABLE_IN_EXPRESSION {  var => REF (vac::PLAIN_VARIABLE { varhome => vh::HIGHCODE_VARIABLE v, ... } ),  ...  }
                                =>
                                if (v == our_root_variable)   raise exception IS_RECURSIVE;    fi;

                            ds::VARIABLE_IN_EXPRESSION _               => ();
                            ds::RECORD_IN_EXPRESSION l                 => apply (\\ (lab, x) = check_exp x)  l;
                            ds::SEQUENTIAL_EXPRESSIONS l               => apply check_exp l;

                            ds::APPLY_EXPRESSION { operator, operand } => { check_exp operator; check_exp operand;};
                            ds::TYPE_CONSTRAINT_EXPRESSION (x, _)      =>   check_exp x;
                            ds::EXCEPT_EXPRESSION (x, (l, _))          => { check_exp x;   apply   (\\ ds::CASE_RULE (_, x) =  check_exp x)   l;};

                            ds::RAISE_EXPRESSION (x, _)     =>   check_exp x;
                            ds::LET_EXPRESSION   (d, x)     => { check_dec d;   check_exp x;};
                            ds::CASE_EXPRESSION  (x, l, _)  => { check_exp x;   apply   (\\ ds::CASE_RULE (_, x) =  check_exp x)   l; };

                            ds::IF_EXPRESSION { test_case, then_case, else_case }
                                =>
                                {   check_exp test_case;
                                    check_exp then_case;
                                    check_exp else_case;
                                };

                            (   ds::AND_EXPRESSION (e1, e2)
                            |   ds::OR_EXPRESSION  (e1, e2)
                            |   ds::WHILE_EXPRESSION { test => e1, expression => e2 }
                            )
                                =>
                                {   check_exp e1;
                                    check_exp e2;
                                };

                            ds::FN_EXPRESSION                     (l, _) =>   apply   (\\ ds::CASE_RULE (_, x) =  check_exp x)   l;
                            ds::SOURCE_CODE_REGION_FOR_EXPRESSION (x, _) =>   check_exp x;
                            ds::RECORD_SELECTOR_EXPRESSION        (_, e) =>   check_exp e;

                            ds::VECTOR_IN_EXPRESSION (el, _)                =>   apply check_exp el;

                            ds::ABSTRACTION_PACKING_EXPRESSION (e, _, _) =>   check_exp e;

                            ( ds::VALCON_IN_EXPRESSION _
                            | ds::INT_CONSTANT_IN_EXPRESSION _
                            | ds::UNT_CONSTANT_IN_EXPRESSION _
                            | ds::FLOAT_CONSTANT_IN_EXPRESSION _
                            | ds::STRING_CONSTANT_IN_EXPRESSION _
                            | ds::CHAR_CONSTANT_IN_EXPRESSION _
                            )
                            => ();
                        esac


                    # All we do here is raise IS_RECURSIVE
                    # if 'd' anywhere contains 'our_root_variable':
                    #
                    also
                    fun check_dec d                                     # 'd' == 'dec' == 'declaration'
                        =
                        case d
                            #
                            ds::VALUE_DECLARATIONS            vbl =>  apply (\\ (ds::VALUE_NAMING            { expression, ... } ) =  check_exp expression)  vbl;
                            ds::RECURSIVE_VALUE_DECLARATIONS rvbl =>  apply (\\ (ds::NAMED_RECURSIVE_VALUE { expression, ... } ) =  check_exp expression)  rvbl;
                            ds::LOCAL_DECLARATIONS (a, b)         =>  { check_dec a;  check_dec b;};
                            #
                            ds::SEQUENTIAL_DECLARATIONS l                => apply check_dec l;
                            ds::SOURCE_CODE_REGION_FOR_DECLARATION (declaration, _) => check_dec declaration;

                            _ => ();
                        esac;
                end;


            convert_deep_syntax_named_recursive_values_list_to_deep_syntax_value_declarations_or_recursive_value_declarations
               rvbs
               =>
               ds::RECURSIVE_VALUE_DECLARATIONS rvbs;
        end;


        # contains_package_declaration() tests whether there are
        # explicit package declarations in a declaration.
        #
        # This is used in type_package_language when
        # typechecking LOCAL_DECLARATIONS, as a cheap approximate
        # check of whether a declaration contains any
        # generic declarations.
        #
        fun contains_package_declaration (raw::PACKAGE_DECLARATIONS          _) =>   TRUE;
            contains_package_declaration (raw::GENERIC_DECLARATIONS          _) =>   TRUE;

            contains_package_declaration (raw::LOCAL_DECLARATIONS (dec_in, dec_out))
                =>
                contains_package_declaration dec_in    or
                contains_package_declaration dec_out;

            contains_package_declaration (raw::SEQUENTIAL_DECLARATIONS decs)
                =>
                list::exists contains_package_declaration decs;

            contains_package_declaration (raw::SOURCE_CODE_REGION_FOR_DECLARATION (declaration, _))
                =>
                contains_package_declaration declaration;

            contains_package_declaration _ => FALSE;
        end;
    };                                  # package typer_junk 
end;                                    # stipulate


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext