PreviousUpNext

15.4.479  src/lib/compiler/back/top/highcode/highcode-type.pkg

## highcode-type.pkg 
#
# See overview comments in:
#
#     src/lib/compiler/back/top/highcode/highcode-type.api

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

###            "One should expect that the expected
###             can be prevented, but the unexpected
###             should have been expected."
###
###                          -- Norman Augustine


stipulate
    package di  =  debruijn_index;                                      # debruijn_index                is from   src/lib/compiler/front/typer/basics/debruijn-index.pkg
    package err =  error_message;                                       # error_message                 is from   src/lib/compiler/front/basics/errormsg/error-message.pkg
    package hbt =  highcode_basetypes;                                  # highcode_basetypes            is from   src/lib/compiler/back/top/highcode/highcode-basetypes.pkg
    package tmp =  highcode_codetemp;                                   # highcode_codetemp             is from   src/lib/compiler/back/top/highcode/highcode-codetemp.pkg
    package hut =  highcode_uniq_types;                                 # highcode_uniq_types           is from   src/lib/compiler/back/top/highcode/highcode-uniq-types.pkg

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

    say =  global_controls::print::say;
herein

    # We get 'included' by:
    #
    #     src/lib/compiler/back/top/highcode/highcode-form.pkg  

    package   highcode_type
    : (weak)  Highcode_Type                                             # Highcode_Type                 is from   src/lib/compiler/back/top/highcode/highcode-type.api
    {

        # highcode hut::Uniqkind is roughly equivalent to:
        #
        #    hut::Kind 
        #      = TYPE 
        #      | BOXED_TYPE
        #      | TYPESEQ   List( hut::Kind )
        #      | TYPEFUN  (List( hut::Kind ), hut::Kind)
        #      ;
        #
        # We treat Uniqkind as an abstract type
        # to isolate clients from the complexity of the
        # hashconsing machinery;  this has the downside
        # of preventing them from using pattern matching.


        # Some hut::Uniqkind constructors: 
        #
        my plaintype_uniqkind:                   hut::Uniqkind    =   hut::kind_to_uniqkind  hut::kind::PLAINTYPE;
        my boxedtype_uniqkind:                   hut::Uniqkind    =   hut::kind_to_uniqkind  hut::kind::BOXEDTYPE;
        #
        my make_kindseq_uniqkind:                List(hut::Uniqkind)                 -> hut::Uniqkind    =    hut::kind_to_uniqkind  o  hut::kind::KINDSEQ;
        my make_kindfun_uniqkind:               (List(hut::Uniqkind), hut::Uniqkind) -> hut::Uniqkind    =    hut::kind_to_uniqkind  o  hut::kind::KINDFUN;

        # Matching hut::Uniqkind deconstructors: 
        #
        my unpack_plaintype_uniqkind:           hut::Uniqkind -> Void    =    fn _ = ();
        my unpack_boxedtype_uniqkind:           hut::Uniqkind -> Void    =    fn _ = ();
        #
        my unpack_kindseq_uniqkind:      hut::Uniqkind -> List( hut::Uniqkind )
            =
            fn tk
                => 
                case (hut::uniqkind_to_kind tk)
                    #
                    hut::kind::KINDSEQ x   =>   x;
                    _                      =>   bug "unexpected hut::Kind in unpack_kindseq_uniqkind";
                esac;
            end;  

        my unpack_kindfun_uniqkind:    hut::Uniqkind -> (List( hut::Uniqkind ), hut::Uniqkind)
            =
            fn tk
                =
                case (hut::uniqkind_to_kind tk)
                    #
                    hut::kind::KINDFUN x   =>   x;
                    _                              =>   bug "unexpected hut::Kind in unpack_kindfun_uniqkind";
                esac;


        # Some hut::Uniqkind predicates:
        #
        my uniqkind_is_plaintype:       hut::Uniqkind -> Bool =  fn tk =  hut::same_uniqkind (tk, plaintype_uniqkind);
        my uniqkind_is_boxedtype:               hut::Uniqkind -> Bool =  fn tk =  hut::same_uniqkind (tk, boxedtype_uniqkind);
        #
        my uniqkind_is_kindseq:         hut::Uniqkind -> Bool =  fn tk =  case (hut::uniqkind_to_kind  tk)    hut::kind::KINDSEQ _ => TRUE;  _ => FALSE;  esac;
        my uniqkind_is_kindfun:         hut::Uniqkind -> Bool =  fn tk =  case (hut::uniqkind_to_kind  tk)    hut::kind::KINDFUN _ => TRUE;  _ => FALSE;  esac;



        # Some hut::Uniqkind one-arm switches:
        #
        fun if_uniqkind_is_plaintype (tk, f, g) =  if (hut::same_uniqkind (tk, plaintype_uniqkind))  f ();  else g tk;  fi;
        fun if_uniqkind_is_boxedtype       (tk, f, g) =  if (hut::same_uniqkind (tk, boxedtype_uniqkind      ))  f ();  else g tk;  fi;
        #
        fun if_uniqkind_is_kindseq    (tk, f, g) =  case (hut::uniqkind_to_kind  tk)    hut::kind::KINDSEQ x => f x;  _ => g tk; esac;
        fun if_uniqkind_is_kindfun         (tk, f, g) =  case (hut::uniqkind_to_kind  tk)    hut::kind::KINDFUN x => f x;  _ => g tk; esac;



        # Highcode Calling_Convention and Useless_Recordflag are used to classify different kinds of typelocked 
        # functions and records. As of now, they are roughly equivalent to:
        #
        #    Calling_Convention
        #      = FIXED_CALLING_CONVENTION
        #      | VARIABLE_CALLING_CONVENTION { arg_is_raw:  Bool,
        #                                         body_is_raw: Bool
        #                                       }
        #
        #    Useless_Recordflag = USELESS_RECORDFLAG
        #
        # We treat both as abstract types so pattern matching no longer applies.
        # NOTE: VARIABLE_CALLING_CONVENTION flags are used by HIGHCODEs before we perform representation
        # analysis while FIXED_CALLING_CONVENTION is used by HIGHCODEs after we perform representation
        # analysis. 


        # Calling_Convention and record_flag constructors:
        #
        my fixed_calling_convention:   hut::Calling_Convention  =   hut::FIXED_CALLING_CONVENTION;
        my useless_recordflag:          hut::Useless_Recordflag =   hut::USELESS_RECORDFLAG;
        #
        my make_variable_calling_convention:  { arg_is_raw: Bool, body_is_raw: Bool }   ->   hut::Calling_Convention
            =
            fn  arg_is_raw__body_is_raw
                =
                hut::VARIABLE_CALLING_CONVENTION   arg_is_raw__body_is_raw;



        # Calling_Convention and Useless_Recordflag deconstructors:
        #
        my unpack_variable_calling_convention:     hut::Calling_Convention -> { arg_is_raw: Bool, body_is_raw: Bool }           # This function is never used.
            =
            fn x =  case x
                        #
                        hut::VARIABLE_CALLING_CONVENTION   arg_is_raw__body_is_raw
                            =>                             arg_is_raw__body_is_raw;

                        _   =>  bug "unexpected Calling_Convention in unpack_variable_calling_convention";
                    esac;


        my unpack_fixed_calling_convention:   hut::Calling_Convention -> Void
            =
            fn x =  case x    hut::FIXED_CALLING_CONVENTION =>  ();
                              _                             =>  bug "unexpected Calling_Convention in unpack_fixed_calling_convention";
                    esac;


        my unpack_useless_recordflag:     hut::Useless_Recordflag -> Void
            =
            fn (hut::USELESS_RECORDFLAG) = ();



        # Calling_Convention and Useless_Recordflag predicates:
        #
        my calling_convention_is_variable:     hut::Calling_Convention -> Bool
            =
            fn x =  case x    hut::VARIABLE_CALLING_CONVENTION _ =>  TRUE;
                              _                     =>  FALSE;
                    esac;


        my calling_convention_is_fixed:   hut::Calling_Convention -> Bool
            =
            fn x =  case x    hut::FIXED_CALLING_CONVENTION =>  TRUE;
                              _                 =>  FALSE;
                    esac;


        my useless_recordflag_is:     hut::Useless_Recordflag -> Bool
            =
            fn (hut::USELESS_RECORDFLAG) =  TRUE;



        # Calling_Convention and Useless_Recordflag one-arm switches: 
        #
        fun if_calling_convention_is_variable (calling_convention, then_fn, else_fn)
            = 
            case calling_convention
                #
                hut::VARIABLE_CALLING_CONVENTION   arg_is_raw__body_is_raw =>  then_fn arg_is_raw__body_is_raw;
                _                                                          =>  else_fn calling_convention;
            esac;


        fun if_calling_convention_is_fixed (calling_convention, then_fn, else_fn)
            = 
            case calling_convention
                #
                hut::FIXED_CALLING_CONVENTION =>  then_fn ();
                _                             =>  else_fn calling_convention;
            esac;


        fun if_useless_recordflag_is (rf, then_fn, else_fn)             # Useless fn on a useless value. :-)
            =
            then_fn ();


        # highcode hut::Uniqtyp is roughly equivalent
        # to the following Mythryl datatype:
        #
        #    Uniqtyp
        #      = TYPEVAR        (Debruijn_Index, Int)
        #      | NAMED_TYPEVAR   tmp::Codetemp
        #      | BASETYPE        hut::Basetype
        #      | TYPEFUN         (List( hut::Uniqkind ), hut::Uniqtyp)
        #      | APPLY_TYPEFUN      (hut::Uniqtyp, List( hut::Uniqtyp ))
        #      | TYPESEQ   List( hut::Uniqtyp )
        #      | TYPE_PROJECTION (hut::Uniqtyp, Int)
        #      | SUM_TYPE        List( hut::Uniqtyp )
        #      | RECURSIVE_TYPE  (hut::Uniqtyp, Int)
        #      | TUPLE_TYPE      List( hut::Uniqtyp )           #  record_flag hidden 
        #      | ARROW_TYPE     (hut::Calling_Convention, List(hut::Uniqtyp), List(hut::Uniqtyp))
        #      | BOXED_TYPE       hut::Uniqtyp
        #      | ABSTRACT_TYPE   hut::Uniqtyp 
        #      | EXTENSIBLE_TOKEN_TYPE  (Token, hut::Uniqtyp)
        #      | FATE_TYPE              List(hut::Uniqtyp)
        #      | INDIRECT_TYPE_THUNK   (hut::Uniqtyp, hut::Uniqtype)
        #      | TYPE_CLOSURE  (Uniqtyp, Int, Int, Uniqtyp_Dictionary)
        #      ;        
        #
        # We treat Uniqtyp as an abstract type
        # to isolate clients from the complexity of the
        # hashconsing machinery;  this has the downside
        # of preventing them from using pattern matching.
        # 
        # hut::Uniqtyp applications (TC_APPLY) and projections 
        # (TC_PROJ) are automatically reduced as needed, that is, the
        # client does not need to worry about whether a hut::Uniqtyp is in the
        # normal form or not, all functions defined here automatically 
        # take care of this.


        # Some hut::Uniqtyp constructors 
        #
        my make_debruijn_typevar_uniqtyp:       (di::Debruijn_Index, Int)               -> hut::Uniqtyp =  hut::typ_to_uniqtyp o hut::typ::DEBRUIJN_TYPEVAR;
        my make_named_typevar_uniqtyp:           tmp::Codetemp                          -> hut::Uniqtyp =  hut::typ_to_uniqtyp o hut::typ::NAMED_TYPEVAR;
        my make_basetype_uniqtyp:                hbt::Basetype                          -> hut::Uniqtyp =  hut::typ_to_uniqtyp o hut::typ::BASETYPE;
        #
        my make_typefun_uniqtyp:                 ( List(hut::Uniqkind),
                                                   hut::Uniqtyp
                                                 )                                      -> hut::Uniqtyp =  hut::typ_to_uniqtyp o hut::typ::TYPEFUN;
        my make_apply_typefun_uniqtyp:           ( hut::Uniqtyp,
                                                   List(hut::Uniqtyp)
                                                 )                                      -> hut::Uniqtyp =  hut::typ_to_uniqtyp o hut::typ::APPLY_TYPEFUN;
        my make_typeseq_uniqtyp:                 List(hut::Uniqtyp)                     -> hut::Uniqtyp =  hut::typ_to_uniqtyp o hut::typ::TYPESEQ;
        my make_ith_in_typeseq_uniqtyp:         (hut::Uniqtyp, Int)                     -> hut::Uniqtyp =  hut::typ_to_uniqtyp o hut::typ::ITH_IN_TYPESEQ;
        #
        my make_sum_uniqtyp:                     List(hut::Uniqtyp)                     -> hut::Uniqtyp =  hut::typ_to_uniqtyp o hut::typ::SUM;
        my make_abstract_uniqtyp:                hut::Uniqtyp                           -> hut::Uniqtyp =  hut::typ_to_uniqtyp o hut::typ::ABSTRACT;
        my make_boxed_uniqtyp:                   hut::Uniqtyp                           -> hut::Uniqtyp =  hut::typ_to_uniqtyp o hut::typ::BOXED; 
        #
        my make_tuple_uniqtyp:                   List(hut::Uniqtyp)                     -> hut::Uniqtyp =  fn ts =  hut::typ_to_uniqtyp (hut::typ::TUPLE (useless_recordflag, ts));
        my make_extensible_token_uniqtyp:        hut::Uniqtyp                           -> hut::Uniqtyp =  fn tc =  hut::typ_to_uniqtyp (hut::typ::EXTENSIBLE_TOKEN (hut::wrap_token, tc));
        #
        my make_arrow_uniqtyp:                  (hut::Calling_Convention, List(hut::Uniqtyp), List(hut::Uniqtyp))       -> hut::Uniqtyp =  hut::make_arrow_uniqtyp;
        my make_recursive_uniqtyp:              ((Int, hut::Uniqtyp,  List(hut::Uniqtyp)), Int)                         -> hut::Uniqtyp =  hut::typ_to_uniqtyp o hut::typ::RECURSIVE;



        # hut::Uniqtyp deconstructors -- these are
        # basically inverse to the above functions:
        #

        my unpack_debruijn_typevar_uniqtyp:     hut::Uniqtyp -> (di::Debruijn_Index, Int)
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::DEBRUIJN_TYPEVAR x =>  x;
                                                       _                            =>  bug "unexpected typ in unpack_debruijn_typevar_uniqtyp";
                     esac;


        my unpack_named_typevar_uniqtyp:    hut::Uniqtyp -> tmp::Codetemp
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::NAMED_TYPEVAR x =>  x;
                                                       _                         =>  bug "unexpected typ in unpack_named_typevar_uniqtyp";
                     esac;


        my unpack_basetype_uniqtyp:    hut::Uniqtyp -> hbt::Basetype
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::BASETYPE x =>  x;
                                                       _                    =>  bug "unexpected typ in unpack_basetype_uniqtyp";
                     esac;


        my unpack_typefun_uniqtyp:      hut::Uniqtyp -> (List( hut::Uniqkind ), hut::Uniqtyp)
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::TYPEFUN x =>  x;
                                                       _                   =>  bug "unexpected hut::Uniqtyp in unpack_typefun_uniqtyp";
                     esac;


        my unpack_apply_typefun_uniqtyp:     hut::Uniqtyp -> (hut::Uniqtyp, List( hut::Uniqtyp ))
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::APPLY_TYPEFUN x =>  x;
                                                       _                         =>  bug "unexpected hut::Uniqtyp in unpack_apply_typefun_uniqtyp";
                     esac;


        my unpack_typeseq_uniqtyp:     hut::Uniqtyp -> List( hut::Uniqtyp )
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::TYPESEQ x =>  x;
                                                       _                   =>  bug "unexpected hut::Uniqtyp in unpack_typeseq_uniqtyp";
                     esac;


        my unpack_ith_in_typeseq_uniqtyp:    hut::Uniqtyp -> (hut::Uniqtyp, Int)
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::ITH_IN_TYPESEQ x =>  x;
                                                       _                          =>  bug "unexpected hut::Uniqtyp in unpack_ith_in_typeseq_uniqtyp";
                     esac;


        my unpack_sum_uniqtyp:     hut::Uniqtyp -> List( hut::Uniqtyp )
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::SUM x =>  x;
                                                       _               =>  bug "unexpected hut::Uniqtyp in unpack_sum_uniqtyp";
                     esac;


        my unpack_recursive_uniqtyp:     hut::Uniqtyp -> (((Int, hut::Uniqtyp,  List( hut::Uniqtyp)) ), Int)
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::RECURSIVE x =>  x;
                                                       _                     =>  bug "unexpected hut::Uniqtyp in unpack_recursive_uniqtyp";
                     esac;


        my unpack_extensible_token_uniqtyp:    hut::Uniqtyp -> hut::Uniqtyp
            =
            fn tc =  case (hut::uniqtyp_to_typ tc)
                         hut::typ::EXTENSIBLE_TOKEN (tk, x)
                             => 
                             if (hut::same_token (tk, hut::wrap_token))  x;
                             else                                        bug "unexpected token hut::Uniqtyp in unpack_extensible_token_uniqtyp";
                             fi;
                         _   => bug "unexpected regular hut::Uniqtyp in unpack_extensible_token_uniqtyp";
                     esac;


        my unpack_abstract_uniqtyp:     hut::Uniqtyp -> hut::Uniqtyp
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::ABSTRACT x =>  x;
                                                       _                    =>  bug "unexpected hut::Uniqtyp in unpack_abstract_uniqtyp";
                     esac;


        my unpack_boxed_uniqtyp:     hut::Uniqtyp -> hut::Uniqtyp
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::BOXED x =>  x;
                                                       _                 =>  bug "unexpected hut::Uniqtyp in unpack_boxed_uniqtyp";
                     esac;


        my unpack_tuple_uniqtyp:   hut::Uniqtyp -> List( hut::Uniqtyp )
             =
             fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::TUPLE (_, x) =>  x;
                                                        _                      =>  bug "unexpected hut::Uniqtyp in unpack_tuple_uniqtyp";
                      esac;


        my unpack_arrow_uniqtyp:   hut::Uniqtyp -> (hut::Calling_Convention, List( hut::Uniqtyp ), List( hut::Uniqtyp ))
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::ARROW x =>  x;
                                                       _                 =>  bug "unexpected hut::Uniqtyp in unpack_arrow_uniqtyp";
                     esac;



        # Some hut::Uniqtyp predicates: 
        #
        my uniqtyp_is_debruijn_typevar:     hut::Uniqtyp -> Bool
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::DEBRUIJN_TYPEVAR _ =>  TRUE;
                                                       _                            =>  FALSE;
                     esac;


        my uniqtyp_is_named_typevar:    hut::Uniqtyp -> Bool
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::NAMED_TYPEVAR _ =>  TRUE;
                                                       _                         =>  FALSE;
                     esac;


        my uniqtyp_is_basetype:    hut::Uniqtyp -> Bool
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::BASETYPE _ =>  TRUE;
                                                       _                    =>  FALSE;
                     esac;


        my uniqtyp_is_typefun:      hut::Uniqtyp -> Bool
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::TYPEFUN _ =>  TRUE;
                                                       _                   =>  FALSE;
                     esac;


        my uniqtyp_is_apply_typefun:     hut::Uniqtyp -> Bool
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::APPLY_TYPEFUN _ =>  TRUE;
                                                       _                         =>  FALSE;
                     esac;


        my uniqtyp_is_typeseq:     hut::Uniqtyp -> Bool
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::TYPESEQ _ =>  TRUE;
                                                       _                   =>  FALSE;
                     esac;


        my uniqtyp_is_ith_in_typeseq:    hut::Uniqtyp -> Bool
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::ITH_IN_TYPESEQ _ =>  TRUE;
                                                       _                          =>  FALSE;
                     esac;


        my uniqtyp_is_sum:     hut::Uniqtyp -> Bool
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::SUM _ =>  TRUE;
                                                       _               =>  FALSE;
                     esac;


        my uniqtyp_is_recursive:     hut::Uniqtyp -> Bool
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::RECURSIVE _ =>  TRUE;
                                                       _                     =>  FALSE;
                     esac;


        my uniqtyp_is_extensible_token:    hut::Uniqtyp -> Bool
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::EXTENSIBLE_TOKEN (tk, _) =>  hut::same_token (tk, hut::wrap_token);
                                                       _                                  =>  FALSE;
                     esac;


        my uniqtyp_is_abstract:     hut::Uniqtyp -> Bool
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::ABSTRACT _ =>  TRUE;
                                                       _                    =>  FALSE;
                     esac;


        my uniqtyp_is_boxed:     hut::Uniqtyp -> Bool
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::BOXED _ =>  TRUE;
                                                       _                 =>  FALSE;
                     esac;


        my uniqtyp_is_tuple:   hut::Uniqtyp -> Bool
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::TUPLE _ =>  TRUE;
                                                       _                 =>  FALSE;
                     esac;


        my uniqtyp_is_arrow:   hut::Uniqtyp -> Bool
            =
            fn tc =  case (hut::uniqtyp_to_typ  tc)    hut::typ::ARROW _ =>  TRUE;
                                                       _                 =>  FALSE;
                     esac;



        # Some hut::Uniqtyp one-arm switches: 
        #
        fun if_uniqtyp_is_debruijn_typevar      (tc, f, g)   =   case (hut::uniqtyp_to_typ tc)    hut::typ::DEBRUIJN_TYPEVAR      x => f x;    _ => g tc;  esac;
        fun if_uniqtyp_is_named_typevar         (tc, f, g)   =   case (hut::uniqtyp_to_typ tc)    hut::typ::NAMED_TYPEVAR         x => f x;    _ => g tc;  esac;
        fun if_uniqtyp_is_basetype              (tc, f, g)   =   case (hut::uniqtyp_to_typ tc)    hut::typ::BASETYPE              x => f x;    _ => g tc;  esac;

        fun if_uniqtyp_is_typefun               (tc, f, g)   =   case (hut::uniqtyp_to_typ tc)    hut::typ::TYPEFUN               x => f x;   _ => g tc;  esac;
        fun if_uniqtyp_is_apply_typefun         (tc, f, g)   =   case (hut::uniqtyp_to_typ tc)    hut::typ::APPLY_TYPEFUN         x => f x;   _ => g tc;  esac;
        fun if_uniqtyp_is_typeseq               (tc, f, g)   =   case (hut::uniqtyp_to_typ tc)    hut::typ::TYPESEQ               x => f x;   _ => g tc;  esac;

        fun if_uniqtyp_is_ith_in_typeseq        (tc, f, g)   =   case (hut::uniqtyp_to_typ tc)    hut::typ::ITH_IN_TYPESEQ        x => f x;   _ => g tc;  esac; 
        fun if_uniqtyp_is_sum                   (tc, f, g)   =   case (hut::uniqtyp_to_typ tc)    hut::typ::SUM                   x => f x;   _ => g tc;  esac;  
        fun if_uniqtyp_is_recursive             (tc, f, g)   =   case (hut::uniqtyp_to_typ tc)    hut::typ::RECURSIVE             x => f x;   _ => g tc;  esac;  

        fun if_uniqtyp_is_abstract              (tc, f, g)   =   case (hut::uniqtyp_to_typ tc)    hut::typ::ABSTRACT              x => f x;   _ => g tc;  esac;  
        fun if_uniqtyp_is_boxed                 (tc, f, g)   =   case (hut::uniqtyp_to_typ tc)    hut::typ::BOXED                 x => f x;   _ => g tc;  esac;  

        fun if_uniqtyp_is_tuple                 (tc, f, g)   =   case (hut::uniqtyp_to_typ tc)    hut::typ::TUPLE (_, x) => f x;   _ => g tc;  esac;
        fun if_uniqtyp_is_arrow                 (tc, f, g)   =   case (hut::uniqtyp_to_typ tc)    hut::typ::ARROW x      => f x;   _ => g tc;  esac;

        fun if_uniqtyp_is_extensible_token  (tc, f, g)
            = 
            case (hut::uniqtyp_to_typ tc)
                #
                hut::typ::EXTENSIBLE_TOKEN (rk, x)
                    =>
                    if (hut::same_token (rk, hut::wrap_token))   f x;
                    else                                             g tc;
                    fi;

                  _ => g tc;
            esac;  



        # highcode hut::Uniqtype is roughly equivalent to:
        #
        #  Type
        #      = TYP                     hut::Uniqtyp
        #      | PACKAGE                 List(hut::Uniqtype)
        #      | GENERIC_PACKAGE        (List(hut::Uniqtype), List(hut::Uniqtype))
        #      | TYPEAGNOSTIC           (List(hut::Uniqkind), List(hut::Uniqtype))
        #
        # We treat Uniqtype as an abstract type
        # to isolate clients from the complexity of the
        # hashconsing machinery;  this has the downside
        # of preventing them from using pattern matching.
        # 
        # Clients do not need to worry about whether an
        # hut::Uniqtype is in normal form or not. 


        # hut::Uniqtype constructors
        #
        my make_typ_uniqtype:                         hut::Uniqtyp                         -> hut::Uniqtype     =       hut::type_to_uniqtype o hut::type::TYP;
        my make_package_uniqtype:                List(hut::Uniqtype)                       -> hut::Uniqtype     =       hut::type_to_uniqtype o hut::type::PACKAGE;
        my make_generic_package_uniqtype:       (List(hut::Uniqtype), List(hut::Uniqtype)) -> hut::Uniqtype     =       hut::type_to_uniqtype o hut::type::GENERIC_PACKAGE;
        my make_typeagnostic_uniqtype:          (List(hut::Uniqkind), List(hut::Uniqtype)) -> hut::Uniqtype     =       hut::type_to_uniqtype o hut::type::TYPEAGNOSTIC;



        # hut::Uniqtype deconstructors
        #
        my unpack_typ_uniqtype:     hut::Uniqtype -> hut::Uniqtyp
            =
            fn lt =  case (hut::uniqtype_to_type lt) hut::type::TYP x                =>  x;
                                                     hut::type::PACKAGE            _ =>  bug "hut::type::PACKAGE unsupported in unpack_typ_uniqtype";
                                                     hut::type::GENERIC_PACKAGE    _ =>  bug "hut::type::GENERIC unsupported in unpack_typ_uniqtype";
                                                     hut::type::TYPEAGNOSTIC       _ =>  bug "hut::type::TYPEAGNOSTIC unsupported in unpack_typ_uniqtype";
                                                     _                               =>  bug "Unexpected hut::Uniqtype in unpack_typ_uniqtype";
                     esac;


        my unpack_package_uniqtype:     hut::Uniqtype ->  List( hut::Uniqtype )
            =
            fn lt =  case (hut::uniqtype_to_type lt)
                         #
                         hut::type::PACKAGE x =>  x;
                         _                    =>  bug "unexpected hut::Uniqtype in unpack_package_uniqtype";
                     esac;


        my unpack_generic_package_uniqtype:     hut::Uniqtype ->  (List( hut::Uniqtype ), List( hut::Uniqtype ))
            =
            fn lt =  case (hut::uniqtype_to_type lt)
                         #
                         hut::type::GENERIC_PACKAGE x =>  x;
                         _                            =>  bug "unexpected hut::Uniqtype in unpack_generic_package_uniqtype";
                     esac;


        my unpack_typeagnostic_uniqtype:    hut::Uniqtype -> (List( hut::Uniqkind ), List( hut::Uniqtype ))
            =
            fn lt =  case (hut::uniqtype_to_type lt)
                         #
                         hut::type::TYPEAGNOSTIC x =>  x;
                         _                         =>  bug "unexpected hut::Uniqtype in unpack_typeagnostic_uniqtype";
                     esac;



        # hut::Uniqtype predicates 
        #
        my uniqtype_is_typ:     hut::Uniqtype -> Bool
            =
            fn lt =  case (hut::uniqtype_to_type lt)
                         #
                         hut::type::TYP _ =>  TRUE;
                         _                =>  FALSE;
                     esac;


        my uniqtype_is_package:     hut::Uniqtype -> Bool
            =
            fn lt =  case (hut::uniqtype_to_type lt)
                         #
                         hut::type::PACKAGE _ =>  TRUE;
                         _                    =>  FALSE;
                     esac;


        my uniqtype_is_generic_package:     hut::Uniqtype -> Bool
            =
            fn lt =  case (hut::uniqtype_to_type lt)
                         #
                         hut::type::GENERIC_PACKAGE _ =>  TRUE;
                         _                            =>  FALSE;
                     esac;


        my uniqtype_is_typeagnostic:    hut::Uniqtype -> Bool
            =
            fn lt =  case (hut::uniqtype_to_type lt)
                         #
                         hut::type::TYPEAGNOSTIC _ =>  TRUE;
                         _                         =>  FALSE;
                     esac;



        # hut::Uniqtype one-arm switches.
        # These are if-then-else constructs which may be
        # daisy-chained to implement a complete 'case' statement:
        #
        fun if_uniqtype_is_typ                  (lt, f, g) =  case (hut::uniqtype_to_type lt)    hut::type::TYP              x => f x;  _ => g lt;      esac;
        fun if_uniqtype_is_package              (lt, f, g) =  case (hut::uniqtype_to_type lt)    hut::type::PACKAGE          x => f x;  _ => g lt;      esac;
        fun if_uniqtype_is_generic_package      (lt, f, g) =  case (hut::uniqtype_to_type lt)    hut::type::GENERIC_PACKAGE  x => f x;  _ => g lt;      esac;
        fun if_uniqtype_is_typeagnostic         (lt, f, g) =  case (hut::uniqtype_to_type lt)    hut::type::TYPEAGNOSTIC     x => f x;  _ => g lt;      esac;


        # Because highcode hut::Uniqtyp is embedded inside
        # highcode hut::Uniqtype, we supply the the following
        # utility functions for building types that are based
        # on simple typelocked typs.



        # hut::Uniqtyp-hut::Uniqtype constructors 
        #
        my make_debruijn_typevar_uniqtype:      (di::Debruijn_Index, Int)  -> hut::Uniqtype     =  make_typ_uniqtype o make_debruijn_typevar_uniqtyp;
        my make_basetype_uniqtype:               hbt::Basetype             -> hut::Uniqtype     =  make_typ_uniqtype o make_basetype_uniqtyp;
        my make_tuple_uniqtype:                  List(hut::Uniqtype)       -> hut::Uniqtype     =  make_typ_uniqtype o (make_tuple_uniqtyp o (map unpack_typ_uniqtype));
        #
        my make_arrow_uniqtype:   (hut::Calling_Convention,  List( hut::Uniqtype ),  List( hut::Uniqtype )) -> hut::Uniqtype
            =
            fn (r, t1, t2)
                =
                {   ts1 =  map  unpack_typ_uniqtype  t1;
                    ts2 =  map  unpack_typ_uniqtype  t2;
                    #
                    make_typ_uniqtype (make_arrow_uniqtyp (r, ts1, ts2));
                };



        # Some hut::Uniqtyp-hut::Uniqtype deconstructors 
        #
        my unpack_debruijn_typevar_uniqtype:     hut::Uniqtype -> (di::Debruijn_Index, Int)     =  unpack_debruijn_typevar_uniqtyp o unpack_typ_uniqtype;
        my unpack_basetype_uniqtype:             hut::Uniqtype -> hbt::Basetype                 =  unpack_basetype_uniqtyp o unpack_typ_uniqtype;
        my unpack_tuple_uniqtype:                hut::Uniqtype -> List( hut::Uniqtype )         = (map make_typ_uniqtype)  o (unpack_tuple_uniqtyp o unpack_typ_uniqtype);
        #
        my unpack_arrow_uniqtype:                hut::Uniqtype -> (hut::Calling_Convention, List(hut::Uniqtype),  List(hut::Uniqtype))
            =
            fn t =  {   my (r, ts1, ts2) = unpack_arrow_uniqtyp (unpack_typ_uniqtype t);
                        (r, map make_typ_uniqtype ts1, map make_typ_uniqtype ts2);
                    };



        # Some hut::Uniqtyp-hut::Uniqtype predicates 

        my uniqtype_is_debruijn_typevar:     hut::Uniqtype -> Bool
            =
            fn t =  case (hut::uniqtype_to_type t)    hut::type::TYP x =>  uniqtyp_is_debruijn_typevar x;
                                                      _                =>  FALSE;
                    esac;


        my uniqtype_is_basetype:    hut::Uniqtype -> Bool
            =
            fn t =  case (hut::uniqtype_to_type t)    hut::type::TYP x =>  uniqtyp_is_basetype x;
                                                      _                =>  FALSE;
                    esac;


        my uniqtype_is_tuple_type:   hut::Uniqtype -> Bool
            =
            fn t =  case (hut::uniqtype_to_type t)    hut::type::TYP x =>  uniqtyp_is_tuple x;
                                                      _                =>  FALSE;
                    esac;


        my uniqtype_is_arrow_type:   hut::Uniqtype -> Bool
            =
            fn t =  case (hut::uniqtype_to_type t)    hut::type::TYP x =>  uniqtyp_is_arrow x;
                                                      _                =>  FALSE;
                    esac;



        # Some hut::Uniqtyp-hut::Uniqtype one-arm switches:
        #
        fun if_uniqtype_is_debruijn_typevar (lt, f, g)
            = 
            case (hut::uniqtype_to_type lt)
                 hut::type::TYP tc
                     => 
                     case (hut::uniqtyp_to_typ tc)    hut::typ::DEBRUIJN_TYPEVAR x =>  f x;
                                                      _                   =>  g lt;
                     esac;

                _ => g lt;
            esac;


        fun if_uniqtype_is_basetype (lt, f, g)
            = 
            case (hut::uniqtype_to_type lt)
                hut::type::TYP tc
                    => 
                    case (hut::uniqtyp_to_typ tc)    hut::typ::BASETYPE x =>  f x;
                                                     _                    =>  g lt;
                    esac;
              _ => g lt;
            esac;


        fun if_uniqtype_is_tuple_type (lt, f, g)
            = 
            case (hut::uniqtype_to_type lt)
                hut::type::TYP tc
                    => 
                    case (hut::uniqtyp_to_typ tc)    hut::typ::TUPLE (_, x) =>  f x;
                                                     _                           =>  g lt;
                    esac;
              _ => g lt;
            esac;


        fun if_uniqtype_is_arrow_type (lt, f, g)
            = 
            case (hut::uniqtype_to_type lt)
                #
                hut::type::TYP tc
                    => 
                    case (hut::uniqtyp_to_typ tc)
                        #
                        hut::typ::ARROW x =>  f x;
                        _                      =>  g lt;
                    esac;

               _ => g lt;
            esac;



        #########################################################################3
        # The following functions are written for nextcode only.
        # If you are writing writing code for highcode,
        # you should not use any of these functions. 
        #
        # The fate referred here is the internal
        # fate introduced via nextcode conversion;
        # it is different from the source-level fate 
        # (Fate(X)) or control fate (Control_Fate(X))
        # where are represented  hbt::primTypeCon_fate and
        # hbt::primTypeCon_control_fate respectively. 


        # Our fate-hut::Uniqtyp-hut::Uniqtype constructors
        #
        my make_uniqtyp_fate:   List( hut::Uniqtyp ) -> hut::Uniqtyp  =  hut::typ_to_uniqtyp   o  hut::typ::FATE;
        my make_uniqtype_fate:  List( hut::Uniqtype) -> hut::Uniqtype =  hut::type_to_uniqtype o  hut::type::FATE;


        # Our fate-hut::Uniqtyp-hut::Uniqtype deconstructors.
        # These are inverse to the above two:
        #
        my unpack_uniqtyp_fate:    hut::Uniqtyp -> List( hut::Uniqtyp )
            =
            fn tc =  case (hut::uniqtyp_to_typ tc)    hut::typ::FATE x =>  x;
                                                      _                     =>  bug "unexpected hut::Uniqtyp in unpack_uniqtyp_fate";
                     esac;


        my unpack_uniqtype_fate:    hut::Uniqtype -> List( hut::Uniqtype )
            =
            fn lt =  case (hut::uniqtype_to_type lt)    hut::type::FATE x =>  x; 
                                                        _                               =>  bug "unexpected hut::Uniqtype in unpack_uniqtype_fate";
                     esac;


        # Our fate-hut::Uniqtyp-hut::Uniqtype predicates 
        #
        my uniqtyp_is_fate:    hut::Uniqtyp -> Bool
            =
            fn tc =  case (hut::uniqtyp_to_typ tc)    hut::typ::FATE _ =>  TRUE;
                                                      _                     =>  FALSE;
                     esac;


        my uniqtype_is_fate:    hut::Uniqtype -> Bool
            =
            fn lt =  case (hut::uniqtype_to_type lt)    hut::type::FATE _ =>  TRUE;
                                                        _                               =>  FALSE;
                     esac;



        #  Our fate-hut::Uniqtyp-hut::Uniqtype one-arm switches 

        fun if_uniqtyp_is_fate (tc, f, g)
            = 
            case (hut::uniqtyp_to_typ tc)    hut::typ::FATE x =>  f x;
                                             _                     =>  g tc;
            esac; 


        fun if_uniqtype_is_fate (lt, f, g)
            = 
            case (hut::uniqtype_to_type lt)    hut::type::FATE x =>  f x;
                                               _                               =>  g lt;
            esac;





        ################################################################################################
        # The following functions are written for lambdacode_type only. If you
        # are writing code for highcode only, don't use any of these functions. 
        # The idea is that in lambdacode, all (value or type) functions have single
        # argument and single return-result. Ideally, we should define 
        # another sets of datatypes for typs and ltys. But we want to avoid
        # the translation from lambdacode_type to highcode types, so we let them
        # share the same representations as much as possible. 
        #
        # Ultimately, highcode_type should be separated into two files: one for 
        # highcode, another for lambdacode, but we will see if this is necessary.


        # The implementation here is TEMPORARY; Stefan needs to take a look at     XXX BUGGO FIXME
        # this. Note parrow could share the representation with arrow if there 
        # is one-to-one mapping between parrow and arrow.


        # plambda hut::Uniqtyp-hut::Uniqtype constructors
        #
        my make_lambdacode_arrow_uniqtyp:  (hut::Uniqtyp, hut::Uniqtyp) -> hut::Uniqtyp
            =    
            fn (x, y) =  make_arrow_uniqtyp (make_variable_calling_convention { arg_is_raw => FALSE, body_is_raw => FALSE }, [x], [y]);


        my make_lambdacode_arrow_uniqtype:  (hut::Uniqtype, hut::Uniqtype) -> hut::Uniqtype
            =
            fn (x, y) =  make_typ_uniqtype (make_lambdacode_arrow_uniqtyp (unpack_typ_uniqtype x, unpack_typ_uniqtype y));


        my make_lambdacode_typeagnostic_uniqtype:    (List( hut::Uniqkind ), hut::Uniqtype) -> hut::Uniqtype
            =
            fn (ks, t) =  make_typeagnostic_uniqtype (ks, [t]);


        my make_lambdacode_generic_package_uniqtype:    (hut::Uniqtype, hut::Uniqtype) -> hut::Uniqtype
            =
            fn (x, y) =  make_generic_package_uniqtype ([x], [y]);



        # Our* plambda hut::Uniqtyp-hut::Uniqtype deconstructors:
        #
        my unpack_lambdacode_arrow_uniqtyp:  hut::Uniqtyp -> (hut::Uniqtyp, hut::Uniqtyp)
            =
            fn tc =  case (hut::uniqtyp_to_typ tc)
                         #
                         hut::typ::ARROW (_, xs, ys) => (hut::uniqtyp_list_to_uniqtyp_tuple xs, hut::uniqtyp_list_to_uniqtyp_tuple ys);
                         _ => bug "unexpected hut::Uniqtyp in unpack_lambdacode_arrow_uniqtyp";
                     esac;


        my unpack_lambdacode_arrow_uniqtype:  hut::Uniqtype -> (hut::Uniqtype, hut::Uniqtype)
            =
            fn t =  {   my (t1, t2)
                            =
                            unpack_lambdacode_arrow_uniqtyp (unpack_typ_uniqtype t);

                        ( make_typ_uniqtype t1,
                          make_typ_uniqtype t2
                        );
                    };


        my unpack_lambdacode_typeagnostic_uniqtype:   hut::Uniqtype ->  (List( hut::Uniqkind ), hut::Uniqtype)
            =
            fn t =  {   my (ks, ts)
                            =
                            unpack_typeagnostic_uniqtype t;

                        case ts    [x] =>  (ks, x);
                                    _  =>  bug "unexpected case in unpack_lambdacode_typeagnostic_uniqtype";
                        esac;
                     };


        my unpack_lambdacode_generic_package_uniqtype:    hut::Uniqtype -> (hut::Uniqtype, hut::Uniqtype)
            =
            fn t =  {   my (ts1, ts2)
                            =
                            unpack_generic_package_uniqtype t;

                        case (ts1, ts2)    ([x], [y]) =>  (x, y);
                                           _          =>  bug "unexpected case in unpack_lambdacode_generic_package_uniqtype";
                        esac;
                    };



        # Our plambda hut::Uniqtyp-hut::Uniqtype predicates 
        #
        my uniqtyp_is_lambdacode_arrow:  hut::Uniqtyp -> Bool
            =
            fn tc =  case (hut::uniqtyp_to_typ tc)    hut::typ::ARROW (_, [x], [y]) =>  TRUE;
                                                      _                                  =>  FALSE;
                     esac;


        my uniqtype_is_lambdacode_arrow:  hut::Uniqtype -> Bool
            =
            fn t =  case (hut::uniqtype_to_type t)    hut::type::TYP x =>  uniqtyp_is_lambdacode_arrow x;
                                                      _                =>  FALSE;
                    esac;


        my uniqtype_is_lambdacode_typeagnostic:   hut::Uniqtype -> Bool
            =
            fn t =  case (hut::uniqtype_to_type t)    hut::type::TYPEAGNOSTIC (_, [x]) =>  TRUE;
                                                      _                                =>  FALSE;
                    esac;


        my uniqtype_is_lambdacode_generic_package:    hut::Uniqtype -> Bool
            =
            fn t =  case (hut::uniqtype_to_type t)    hut::type::GENERIC_PACKAGE ([x], [y]) =>  TRUE;
                                                      _                                          =>  FALSE;
                    esac;



        # Our plambda hut::Uniqtyp-hut::Uniqtype one-arm switches 
        #
        fun if_uniqtyp_is_lambdacode_arrow (tc, f, g)
            =
            case (hut::uniqtyp_to_typ tc)    hut::typ::ARROW (_,[x],[y]) =>  f (x, y);
                                             _                                =>  g tc;
            esac;


        fun if_uniqtype_is_lambdacode_arrow (lt, f, g)
            = 
            case (hut::uniqtype_to_type lt)
                #
                hut::type::TYP tc
                    => 
                    case (hut::uniqtyp_to_typ tc)    hut::typ::ARROW (_,[x],[y]) =>  f (x, y);
                                                     _                                =>  g lt;
                    esac;

                _ => g lt;
            esac;


        fun if_uniqtype_is_lambdacode_typeagnostic (lt, f, g)
            =
            case (hut::uniqtype_to_type lt)    hut::type::TYPEAGNOSTIC (ks,[x]) =>  f (ks, x);
                                               _                                =>  g lt;
            esac;


        fun if_uniqtype_is_lambdacode_generic_package (lt, f, g)
            =
            case (hut::uniqtype_to_type lt)
                #
                hut::type::GENERIC_PACKAGE ([x],[y]) =>  f (x, y);
                 _                                        =>  g lt;
            esac;

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


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext