PreviousUpNext

15.4.716  src/lib/core/init/core.pkg

## core.pkg

# Compiled by:
#     src/lib/core/init/init.cmi


# 'core' assumes that the following
# are already in the symbol table: 
#
#   1. Built-in packages, defined in base_types, from src/lib/compiler/front/semantic/symbolmapstack/base-types-and-ops.pkg
#        base_types inline
#   
#   2. Built-in type constructors, defined in base_types, from src/lib/compiler/front/semantic/symbolmapstack/base-types-and-ops.pkg
#        Int String Bool Void Float List Rw_Vector Ref Exception
#
#   3. Built-in data constructors, also from base_types, from src/lib/compiler/front/semantic/symbolmapstack/base-types-and-ops.pkg
#        . NIL REF TRUE FALSE
#
#   4. Built-in primitive operators, defined in inline, from src/lib/compiler/front/semantic/symbolmapstack/base-types-and-ops.pkg
#      The inline package is not typed (all values have type alpha, this
#      will change in the future though !). 
#       
#   5. The 'assembly' package, which for typechecking purposes is declared
#      in the file src/lib/core/init/runtime.pkg
#      and whose implementation is provided by the runtime system.
#
# In addition, all matches in this file should be exhaustive; the match and 
# bind exceptions are not defined at this stage of bootup, so any uncaught 
# match will cause an unpredictable error. 



###                     "I am no lazier now than I was forty years ago,
###                      but that is because I reached the limit forty years ago.
###                      You can't go beyond possibility."
###
###                                        -- Mark Twain in Eruption



package core {

    # Our 'runtime' package comes from the hand-crafted (pseudo-) package
    #
    #     runtime_package__global
    #
    # generated in
    #
    #     src/c/main/construct-runtime-package.c
    #
    # and made available at the Mythryl level by
    #
    #     src/c/main/load-compiledfiles.c
    #
    #     "The coercions are implemented via inline::cast, 
    #      a primitive operator hardwired inside the compiler.
    #      In the future, the linkage should be done safely
    #      without using cast."   -- ZHONG
    #
    #     "In the future, the runtime::asm subpackage will be
    #      replaced by a dynamic run vector."  -- John H Reppy
    #
    # Our core::runtime package gets published as just "runtime" in:
    #
    #     src/lib/core/init/built-in.pkg
    #  

    package   runtime
    : (weak)  Runtime                                           # Runtime       is from   src/lib/core/init/runtime.api
    {
        include package   runtime;                              # runtime       is from   src/lib/core/init/runtime.pkg
        #
        cast =  inline::cast:  X -> Y;                          # inline        is from   x

        Pair (X, Y) = PAIR  (X, Y);

        package asm {
            #
            # This package makes available at the Mythryl level
            # the assembly-language functions exported by the
            # platform-specific files
            #
            #   src/c/machine-dependent/prim.intel32.asm
            #   src/c/machine-dependent/prim.sparc32.asm
            #   src/c/machine-dependent/prim.pwrpc32.asm
            #   src/c/machine-dependent/prim.intel32.masm
            #
            Cfunction         =  runtime::asm::Cfunction;
            Unt8_Rw_Vector    =  runtime::asm::Unt8_Rw_Vector;
            Float64_Rw_Vector =  runtime::asm::Float64_Rw_Vector;
            Spin_Lock         =  runtime::asm::Spin_Lock;

            my array_p:                     Pair( Int, X ) -> Rw_Vector(X)      =   cast runtime::asm::make_typeagnostic_rw_vector;
            my make_typeagnostic_rw_vector: (Int, X) -> Rw_Vector(X)            =   \\ x =  array_p (PAIR x);
            my find_cfun_p:                 Pair( String, String ) -> Cfunction =   cast runtime::asm::find_cfun;
            my find_cfun:                  (String, String) -> Cfunction        =   \\ x =  find_cfun_p (PAIR x);
            my call_cfun_p:                 Pair( Cfunction, X ) -> Z           =   cast runtime::asm::call_cfun;
            my call_cfun:                  (Cfunction, X) -> Z                  =   \\ x =  call_cfun_p (PAIR x);

            my make_unt8_rw_vector:         Int -> Unt8_Rw_Vector               =   cast runtime::asm::make_unt8_rw_vector;
            my make_float64_rw_vector:      Int -> Float64_Rw_Vector            =   cast runtime::asm::make_float64_rw_vector;
            my make_string:                 Int -> String                       =   cast runtime::asm::make_string;
            my create_v_p:                  Pair( Int, List(X) ) -> Vector(X)   =   cast runtime::asm::make_typeagnostic_ro_vector;     # ??? What's going on here? 2010-11-21 CrT
            my make_typeagnostic_ro_vector: (Int, List(X)) -> Vector(X)         =   \\ x =  create_v_p (PAIR x);                        # ???



            my floor:    Float -> Int                 =  cast  runtime::asm::floor;
            my logb:     Float -> Int                 =  cast  runtime::asm::logb;
            my scalb_p:  Pair( Float, Int ) -> Float  =  cast  runtime::asm::scalb;

            my scalb:  (Float, Int) -> Float
                    =  \\ x =  scalb_p (PAIR x);

            my try_lock:  Spin_Lock -> Bool   =   cast  runtime::asm::try_lock;
            my unlock:    Spin_Lock -> Void   =   cast  runtime::asm::unlock;
        };

        my zero_length_vector__global:   Vector(X) =   cast  zero_length_vector__global;
    };

    infix  my 80  * / % quot mod rem div;
    infix  my 70 $ ^ + - ;
    infixr my 60 ! . @ ;
    infix  my 50 > < >= <= ;
    infix  my 40 := o;
    infix  my 10 then;

    exception BIND;
    exception MATCH;

    exception RANGE;                    #  for Unt8_Rw_Vector update 
    exception INDEX_OUT_OF_BOUNDS;      #  for all bounds checking 
    exception SIZE; 

    stipulate
        exception NO_PROFILER;
    herein
        register_package_for_time_profiling                                                                             # This gets set to a useful value in   src/lib/std/src/nj/runtime-profiling-control.pkg
            =
            REF (\\ s: String = (raise exception NO_PROFILER): (Int, Rw_Vector( Int ), Ref( Int )) );
    end;

    stipulate
        #
        my ieql:  (Int, Int) -> Bool                    = inline::ti1_eq;
        my peql:  (X, X) -> Bool                        = inline::ptreql;
        my ineq:  (Int, Int) -> Bool                    = inline::ti1_ne;
        my i32eq:  (Int1, Int1) -> Bool                 = inline::i1_eq;
        #
        my boxed:  X -> Bool                            = inline::boxed;
        #
        my (+) : (Int, Int) -> Int                      = inline::ti1_add;
        my (-) : (Int, Int) -> Int                      = inline::ti1_subtract;
        my (*) : (Int, Int) -> Int                      = inline::ti1_mul;
        #
        my (:=): (Ref(X), X) -> Void                    = (inline::(:=));
        #
        my ro_int8_vec_get:  (String, Int) -> Int       = inline::ro_int8_vector_get;
        my cast:  X -> Y                                = inline::cast;
        #
        my get_chunk_tag:  X -> Int                     = inline::gettag;
        my get_chunk_len:  X -> Int                     = inline::chunklength;
        my get_data:  X -> Y                            = inline::get_vector_datachunk;
        #
        my rec_get:  ((X, Int)) -> Y                    = inline::record_get;
        my vec_len:  X -> Int                           = inline::length;
        my vec_get:  (Vector(X), Int) -> X              = inline::ro_vector_get;
        #
        my bitwise_and:  (Int, Int) -> Int              = inline::ti1_bitwise_and;

        width_tags = 0u7;  #  5 tag bits plus "10" 

        # "The type annotation is just to work around an bug."
        #                         -- sm 
        #
        my ltu:  (Int, Int) -> Bool
            =
            inline::ti1_ltu;

    herein 

        # Limit of vector, string, etc. element count is
        # one greater than the maximum length field value.
        # (Sign bit must be zero).
        #       
        maximum_vector_length
            =
            {   (-) =   inline::tu1_subtract;
                #
                infix my << ;

                (<<) =   inline::tu1_lshift;

                int =   inline::copy_31_31_ui;

                int ((0u1 << (0u31 - width_tags)) - 0u1);
            };


        # WARNING: This function is referenced indirectly in
        #     src/lib/compiler/back/top/translate/translate-deep-syntax-to-lambdacode.pkg
        # via the code
        #     core_get "make_vector"
        #
        fun make_vector (n, init)                                       # Renaming?  See note [1].
            = 
            if (ieql (n, 0))
                #               
                inline::make_zero_length_vector ();
            else
                if (ltu (maximum_vector_length, n))   raise exception SIZE;     fi;
                #
                runtime::asm::make_typeagnostic_rw_vector (n, init);
            fi;


        stipulate
            make_float_vector_prim
                =
                inline::cast  runtime::asm::make_float64_rw_vector
                :
                Int -> Rw_Vector(Float);
        herein

            # WARNING: This function is referenced indirectly in
            #     src/lib/compiler/back/top/translate/translate-deep-syntax-to-lambdacode.pkg
            # via the code
            #     core_get "make_float_vector"
            #
            fun make_float_vector (n:  Int, v:  Float) : Rw_Vector( Float )                                     # Renaming?  See note [1].
                =
                if (ieql (n, 0))
                    #               
                    inline::make_zero_length_vector ();
                else
                    if (ltu (maximum_vector_length, n))         raise exception SIZE;   fi;
                    #
                    x =  make_float_vector_prim  n;

                    init 0
                    where
                        fun init i
                            = 
                            if (ieql (i, n))
                                #
                                x;
                            else 
                                inline::rw_f64_vector_set (x, i, v); 
                                init ((+) (i, 1));
                            fi;
                    end;
                fi;
        end;

        zero_length_vector__global =   runtime::zero_length_vector__global;                     # Needed to compile ``#[]''.


        # LAZY: The following definitions are essentially stolen from
        #  lib7::Suspension.  Unfortunately, they had to be copied here in
        #  order to implement laziness (in particular, in order to be
        #  able to compute picklehashes for them.)

        stipulate
            package suspension
            :
            api {
                 Suspension(X);
                 delay:  (Void -> X) -> Suspension(X);
                 force:  Suspension(X) -> X;
            }
            =
            package {

                # WARNING! The following is hard-wired
                # and should track the
                #     src/c/h/heap-tags.h
                # definitions
                #     #define UNEVALUATED_LAZY_SUSPENSION_CTAG  0       // Unevaluated suspension.
                #     #define   EVALUATED_LAZY_SUSPENSION_CTAG  1       //   Evaluated suspension.
                # and the
                #     src/lib/compiler/back/low/main/main/heap-tags.pkg
                # definitions
                #     unevaluated_lazy_suspension_ctag = 0;
                #     evaluated_lazy_suspension_ctag   = 1;
                #
                unevaluated_lazy_suspension_ctag =  0;
                  evaluated_lazy_suspension_ctag =  1;


                Suspension X           #  Just a hack for bootstrapping: 
                    =
                    SOMETHING  X;

                # WARNING: This function is invoked indirectly in
                #     src/lib/compiler/back/top/translate/translate-deep-syntax-to-lambdacode.pkg
                # by doing
                #     core_get "delay"
                #
                fun delay (f:  Void -> X)                                                                               # Renaming?  See note [1].
                    =
                    inline::make_special (unevaluated_lazy_suspension_ctag, f): Suspension(X);


                # WARNING: This function is invoked indirectly in
                #     src/lib/compiler/back/top/translate/translate-deep-syntax-to-lambdacode.pkg
                # by doing
                #     core_get "force"
                #
                fun force (x:  Suspension(X))                                                                           # Renaming?  See note [1].
                    =
                    if (inline::ti1_eq((inline::getspecial x), unevaluated_lazy_suspension_ctag))                       # NB: 'not' is not defined yet!
                        #
                        my y:  X = rec_get (inline::cast x, 0) ();
                        inline::cast x := y;
                        inline::setspecial (inline::cast x, evaluated_lazy_suspension_ctag);
                        y;
                    else
                        rec_get (inline::cast x, 0);
                    fi;
            };
       herein
           include package   suspension;
       end;

       #  Equality primitives 

        # WARNING: This function is referenced in
        #     src/lib/compiler/back/top/translate/translate-deep-syntax-to-lambdacode.pkg
        # via the code
        #     core_get "string_equal"
        #
        fun string_equal (a:  String, b:  String)                                                                       # Renaming?  See note [1].
            =
            if (peql (a, b))
                #
                TRUE;
            else
                len =   vec_len  a;

                if (ieql  (len,  vec_len b))
                    #
                    f len
                    where
                        fun f 0 =>  TRUE;
                            #
                            f i =>  {   j = i - 1;
                                        ieql (ro_int8_vec_get (a, j), ro_int8_vec_get (b, j)) and f j;
                                    };
                        end;
                    end;                    
                else
                    FALSE;
                fi;
            fi;

        # WARNING: This function is referenced in
        #     src/lib/compiler/back/top/translate/translate-deep-syntax-to-lambdacode.pkg
        # via the code
        #     core_get "poly_equal"
        #
        fun poly_equal
              ( a:  X,
                b:  X
              )
            =
            peql (a, b)
            or
            (   boxed a
                and
                boxed b
                and
                {
                    # NOTE: Since the heapcleaner may strip
                    # the header from the pair in question,
                    # we must fetch the length before getting
                    # the tag, whenever we might be dealing
                    # with a pair.

                    a_len = get_chunk_len a;
                    a_tag = get_chunk_tag a;

                    fun pair_eq ()
                        =
                        {
                            b_len = get_chunk_len b;
                            b_tag = get_chunk_tag b;

                            ((ieql (b_tag, 0x02) and ieql (b_len, 2))
                              or ineq (bitwise_and (b_tag, 0x3), 0x2))
                            and poly_equal (rec_get (a, 0), rec_get (b, 0))
                            and poly_equal (rec_get (a, 1), rec_get (b, 1));
                          };

                    fun eq_vec_data (len, a, b)
                        =
                        f 0
                        where
                            fun f i
                                =
                                ieql (i, len)
                                or (poly_equal (rec_get (a, i), rec_get (b, i))
                                  and f (i+1));

                        end;

                    case a_tag
                        #
                        0x02    # pairs_and_records_btag        from    src/lib/compiler/back/low/main/main/heap-tags.pkg
                            =>
                            (ieql (a_len, 2) and pair_eq())
                            or (
                             ieql (get_chunk_tag b, 0x02) and ieql (get_chunk_len b, a_len)
                             and eq_vec_data (a_len, a, b));
                        #
                        0x06    # ro_vector_header_btag from    src/lib/compiler/back/low/main/main/heap-tags.pkg
                            =>
                            # Length encodes element type:
                            #
                            case (get_chunk_len a)
                                #
                                0       # typeagnostic_vector_ctag      see   src/lib/compiler/back/low/main/main/heap-tags.pkg
                                    =>
                                    {   a_len = vec_len a;
                                        b_len = vec_len b;

                                        ieql (a_len, b_len)
                                        and eq_vec_data (a_len, get_data a, get_data b);
                                    };
                                #
                                1 # vector_of_one_byte_unts_ctag
                                    =>
                                    string_equal (cast a, cast b);
                                #
                                _   => raise exception MATCH;                           # Shut up compiler.
                            esac;
                        #
                        0x0a /* rw_vector_header_btag */              =>  peql (get_data a, get_data b);                        # rw_vector_header_btag         def in    src/lib/compiler/back/low/main/main/heap-tags.pkg
                        0x0e /* rw_vector_data_btag and refcell_btag */ =>  FALSE;                                              # rw_vector_data_btag and refcell_btag def in    src/lib/compiler/back/low/main/main/heap-tags.pkg
                        0x12 /* four_byte_aligned_nonpointer_data_btag */                =>  i32eq (cast a, cast b);            # four_byte_aligned_nonpointer_data_btag        def in    src/lib/compiler/back/low/main/main/heap-tags.pkg
                        _    /* tagless pair */             =>  pair_eq();
                    esac;
                }
             );

        #  trace/debug/profile generation hooks:
        #
        Tdp_Plugin
          =
          { name:      String,                          # Name identifying plugin.
            save:      Void -> Void -> Void,
            push:      (Int, Int) -> Void -> Void,
            nopush:    (Int, Int) -> Void,
            enter:     (Int, Int) -> Void,
            register:  (Int, Int, Int, String) -> Void
          };

        stipulate

            next = REF 0;
            hook = REF [] :   Ref( List(Tdp_Plugin) );

            my ( *) = inline::deref;

            infix my := ;

            my (:=)   =   inline::(:=);

            fun runwith a f
                =
                f a;

            fun map f
                =
                loop
                where
                    fun loop []      =>  [];
                        loop (h ! t) =>  f h ! loop t;
                    end;
                end;


            fun apply f
                =
                loop
                where
                    fun loop []      =>   ();
                        loop (h ! t) =>   { f h;  loop t;};
                    end;
                end;


            fun revmap f l
                =
                loop (l, [])
                where
                    fun loop ([],    a) =>  a;
                        loop (h ! t, a) =>  loop (t, f h ! a);
                    end;
                end;


            fun onestage sel ()
                =
                {   fns = map sel *hook;

                    \\ arg =  apply  (runwith arg)  fns;
                };

            fun twostage sel ()
                =
                {   stage1_fns = map sel *hook;

                    \\ arg
                        =
                        {   stage2_fns = revmap (runwith arg) stage1_fns;

                            \\ () =  apply (runwith ()) stage2_fns;
                        };
                };

        herein

            fun tdp_reserve n
                =
                {   r = *next;
                    next := r + n;
                    r;
                };

            fun tdp_reset ()
                =
                next := 0;



            #  pre-defined kinds of IDs (to be passed to "register") 

            tdp_idk_entry_point   = 0;                                                  # "idk" == "id_kind".
            tdp_idk_non_tail_call = 1;
            tdp_idk_tail_call     = 2;

            tdp_save     =  twostage .save;
            tdp_push     =  twostage .push;

            tdp_nopush   =  onestage .nopush;
            tdp_enter    =  onestage .enter;
            tdp_register =  onestage .register;

            tdp_active_plugins = hook;                                                  # This is referenced (only) in  src/lib/std/src/nj/runtime-internals.pkg
        end;

        assign      = inline::(:=);
        deref       = inline::deref;

        unboxed_set = inline::unboxed_set;
        get         = inline::rw_vector_get;
        iadd        = inline::ti1_add;

        # WARNING: All of the following definitions are referenced in
        #     src/lib/compiler/back/top/translate/translate-deep-syntax-to-lambdacode.pkg
        # via core_get -- for example
        #     core_get "make_neg_inf"
        #
        test_inf           = core_multiword_int::test_inf;                                      # Renaming?  See note [1].
        trunc_inf          = core_multiword_int::trunc_inf;                                     # Renaming?  See note [1].
        fin_to_inf         = core_multiword_int::fin_to_inf;                                    # Renaming?  See note [1].
        #
        make_neg_inf       = core_multiword_int::make_neg_inf;                          # Renaming?  See note [1].
        make_pos_inf       = core_multiword_int::make_pos_inf;                          # Renaming?  See note [1].
        #
        make_small_neg_inf = core_multiword_int::make_small_neg_inf;                            # Renaming?  See note [1].
        make_small_pos_inf = core_multiword_int::make_small_pos_inf;                            # Renaming?  See note [1].
        #
        inf_low_value      = core_multiword_int::low_value;                                     # Renaming?  See note [1].

    end;                                                                                # stipulate

    space_profiling_register
        =
        REF (\\ (x: runtime::Chunk,  s: String)  =  x);

};                                                                                      # package core

###############################################################################################
#                                  Notes
#
# Note [1]:   The names
#
#                 make_vector
#                 mk_real_array
#                 delay
#                 force
#                 string_equal
#                 poly_equal
#                 make_neg_inf
#                 make_pos_inf
#                 make_small_neg_inf
#                 make_small_pos_inf
#                 inf_low_value
#                 test_inf
#                 trunc_inf
#                 fin_to_inf
#
#             are hardwired into

#                 src/lib/compiler/back/top/translate/translate-deep-syntax-to-lambdacode.pkg
#
#             so a straightforward attempt to rename will crash you with a message like
#
#                 FATAL:  Unable to fetch 'make_vector' from core.pkg! -- translate-deep-syntax-to-lambdacode.pkg
#
#             One workaround is to rename in three steps:
#
#                 1)  Create a synonym "make_normal_vector" or whatever
#                     with the desired new name and do a full
#                         make compiler
#                         make rest
#                         sudo make install; make check
#                         make tart
#                     compile cycle to establish it.
#
#                 2)  Replace all "make_vector" references
#                     with "make_normal_vector" references and do a
#                     full compile cycle.
#
#                 3)  Remove the now-unneeded "make_vector" and do a
#                     full compile cycle.
#
#             (You may be able to collapse 2) and 3) into one cycle.)


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext