PreviousUpNext

15.4.509  src/lib/compiler/back/top/main/make-nextcode-literals-bytecode-vector.pkg

## make-nextcode-literals-bytecode-vector.pkg

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



# This file implements one of the nextcode transforms.
# For context, see the comments in
#
#     src/lib/compiler/back/top/highcode/highcode-form.api



###                "There is no such thing as group
###                 originality or group creativity."
###
###                                 -- Edwin Land



stipulate
    package ncf =  nextcode_form;                       # nextcode_form                         is from   src/lib/compiler/back/top/nextcode/nextcode-form.pkg
herein

    api Make_Nextcode_Literals_Bytecode_Vector {
        #
        Literal_Expression;

        split_off_nextcode_literals
            :
            ncf::Function -> (ncf::Function, Literal_Expression);


        make_nextcode_literals_bytecode_vector
            :
            Literal_Expression -> vector_of_one_byte_unts::Vector;
    };
end;



stipulate
    package err =  error_message;                       # error_message                         is from   src/lib/compiler/front/basics/errormsg/error-message.pkg
    package ncf =  nextcode_form;                       # nextcode_form                         is from   src/lib/compiler/back/top/nextcode/nextcode-form.pkg
    package hv  =  highcode_codetemp;                   # highcode_codetemp                     is from   src/lib/compiler/back/top/highcode/highcode-codetemp.pkg
    package iht =  int_hashtable;                       # int_hashtable                         is from   src/lib/src/int-hashtable.pkg
    package w8v =  vector_of_one_byte_unts;                             # vector_of_one_byte_unts                               is from   src/lib/std/src/vector-of-one-byte-unts.pkg

    package intset {

        Intset = Ref( int_red_black_set::Set );

        fun new () = REF int_red_black_set::empty;

        fun add set i =  set := int_red_black_set::add(*set, i);
        fun mem set i =         int_red_black_set::member(*set, i);
#       fun rmv set i =  set := int_red_black_set::drop(*set, i);
    };
herein

    package   make_nextcode_literals_bytecode_vector
    : (weak)  Make_Nextcode_Literals_Bytecode_Vector            # Make_Nextcode_Literals_Bytecode_Vector                is from   src/lib/compiler/back/top/main/make-nextcode-literals-bytecode-vector.pkg
    {

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


        ident =   \\ x = x;


        fun make_var _
            =
            hv::issue_highcode_codetemp ();



        # **************************************************************************
        #                         A MINI-LITERAL LANGUAGE                          *
        # **************************************************************************



        Literal_Value
          = LI_INT     Unt
          | LI_STRING  String
          | LI_VAR     ncf::Codetemp
          ;

        Block_Kind
          = LI_RECORD           # Record of tagged Mythryl values.
          | LI_VECTOR           # Vector of tagged Mythryl values.
          ;

        Literal_Expression
          = LI_TOP                    List( Literal_Value )
          | LI_BLOCK     (Block_Kind, List( Literal_Value ),   ncf::Codetemp,   Literal_Expression)
          | LI_F64BLOCK  (            List( String        ),   ncf::Codetemp,   Literal_Expression)
          | LI_I32BLOCK  (            List( one_word_unt::Unt    ),   ncf::Codetemp,   Literal_Expression)
          ;

        fun rk2bk ncf::rk::VECTOR =>  LI_VECTOR;
            rk2bk ncf::rk::RECORD =>  LI_RECORD;
            #
            rk2bk _               =>  bug "rk2bk: unexpected block kind";
        end;

        fun value_to_liternal (ncf::CODETEMP v) =>  LI_VAR v;
            value_to_liternal (ncf::INT      i) =>  LI_INT (unt::from_int i);
            value_to_liternal (ncf::STRING   s) =>  LI_STRING s;
            #
            value_to_liternal _ => bug "unexpected case in value_to_liternal";
        end;



        # **************************************************************************
        #                 TRANSLATING THE LITERAL EXP TO BYTES                     *
        # **************************************************************************



        # Literals are encoded as instructions for a bytecoded "literal machine,"
        # implemented in
        #
        #     src/c/heapcleaner/make-package-literals-via-bytecode-interpreter.c
        #
        # Consequently the bytecode definitions here MUST be kept in sync with the
        # bytecode definitions there!
        #
        # The supported instructions are:
        #
        #       INT (i)                 -- Push the tagged_int literal i on the stack.
        #
        #       RAW32[i1, ..., in]      -- Form a 32-bit raw data record from the
        #                                  i1..in and push a pointer to it.
        #
        #       RAW64[r1, ..., rn]      -- Form a 64-bit raw data record from the
        #                                  r1..rn and push a pointer to it.
        #
        #       STR[c1, ..., cn]        -- Form a string from the characters c1..cn
        #                                  and push it on the stack.
        #
        #       LIT (k)                 -- Push the contents of the stack element
        #                                  that is k slots from the top of the stack.
        #
        #       VECTOR (n)              -- Pop n elements from the stack, make a vector
        #                                  from them and push a pointer to the vector.
        #
        #       RECORD (n)              -- Pop n elements from the stack, make a record
        #                                  from them and push a pointer.
        #
        #       RETURN                  -- Return the top-of-stack literal.


        fun w32to_bytes' (w, l)
            =
            one_byte_unt::from_large_unt   (one_word_unt::(>>) (w, 0u24))
            ! one_byte_unt::from_large_unt (one_word_unt::(>>) (w, 0u16))
            ! one_byte_unt::from_large_unt (one_word_unt::(>>) (w, 0u08))
            ! one_byte_unt::from_large_unt w
            ! l;

        fun w32to_bytes w = w32to_bytes' (w, []);
        fun w31to_bytes w = w32to_bytes (tagged_unt::to_large_unt_x w);

        fun int_to_bytes i       = w32to_bytes (one_word_unt::from_int i);
        fun int_to_bytes' (i, l) = w32to_bytes'(one_word_unt::from_int i, l);

        fun string_to_bytes s
            =
            map byte::char_to_byte (explode s);



        ###                      "A Thaum is the basic unit of magical strength.
        ###                       It has been universally established as the amount
        ###                       of magic needed to create one small white pigeon
        ###                       or three normal-sized billiard balls."
        ###
        ###                                               -- Terry Pratchett



        put_magic =   w8v::from_list [ 0ux19, 0ux98, 0ux10, 0ux22 ];                                    # V1_MAGIC                      in    src/c/heapcleaner/make-package-literals-via-bytecode-interpreter.c

        fun put_depth n = w8v::from_list (int_to_bytes n);
        fun put_int i   = w8v::from_list (0ux01 ! w31to_bytes i);                                       # MAKE_TAGGED_VAL               in    src/c/heapcleaner/make-package-literals-via-bytecode-interpreter.c

        fun put_raw32 [i] => w8v::from_list (0ux02 ! w32to_bytes i);                                    # MAKE_FOUR_BYTE_VAL            in    src/c/heapcleaner/make-package-literals-via-bytecode-interpreter.c
            put_raw32 l =>
              w8v::from_list (0ux03 ! (int_to_bytes'(length l, list::fold_backward w32to_bytes' [] l)));        # MAKE_FOUR_BYTE_VALS_VECTOR    in    src/c/heapcleaner/make-package-literals-via-bytecode-interpreter.c
        end;

        fun put_raw64 [r] => w8v::from_list (0ux04 ! string_to_bytes r);                                # MAKE_EIGHT_BYTE_VAL           in    src/c/heapcleaner/make-package-literals-via-bytecode-interpreter.c
            put_raw64 l => w8v::cat(
              w8v::from_list (0ux05 ! int_to_bytes (length l)) ! map byte::string_to_bytes l);          # MAKE_EIGHT_BYTE_VALS_VECTOR   in    src/c/heapcleaner/make-package-literals-via-bytecode-interpreter.c
        end;

        fun put_string s
            =
            w8v::cat [
                w8v::from_list (0ux06 ! int_to_bytes (size s)),                                         # MAKE_ASCII_STRING             in    src/c/heapcleaner/make-package-literals-via-bytecode-interpreter.c
                byte::string_to_bytes s
              ];

        fun put_lit    k = w8v::from_list (0ux07 ! int_to_bytes k);                                     # GET_ITH_LITERAL               in    src/c/heapcleaner/make-package-literals-via-bytecode-interpreter.c
        fun put_vector n = w8v::from_list (0ux08 ! int_to_bytes n);                                     # MAKE_VECTOR                   in    src/c/heapcleaner/make-package-literals-via-bytecode-interpreter.c
        fun put_record n = w8v::from_list (0ux09 ! int_to_bytes n);                                     # MAKE_RECORD                   in    src/c/heapcleaner/make-package-literals-via-bytecode-interpreter.c

        put_return = w8v::from_list [0uxff];                                                            # RETURN_LAST_LITERAL           in    src/c/heapcleaner/make-package-literals-via-bytecode-interpreter.c



        # This is where we generate the literals bytecode
        # program which will eventually be interpreted by
        #
        #     src/c/heapcleaner/make-package-literals-via-bytecode-interpreter.c
        #       
        fun make_nextcode_literals_bytecode_vector (LI_TOP [])
                =>
                w8v::from_list [];

            make_nextcode_literals_bytecode_vector  lit_expression
                =>
                {       max_depth = depth (lit_expression, 0, 1);

                    code = put_magic
                         ! put_depth max_depth
                         ! list::reverse (put_lit_expression([], lit_expression, []));

                    w8v::cat code;
                }
                where
                    fun depth (LI_TOP ls, d, max_depth)
                            =>
                            int::max (max_depth, d+length ls);

                        depth (LI_BLOCK(_, ls, _, rest), d, max_depth)
                            =>
                            depth (rest, d+1, int::max (max_depth, d+length ls));

                        depth (LI_F64BLOCK (ls, _, rest), d, max_depth)
                            =>
                            depth (rest, d+1, int::max (max_depth, d+length ls));

                        depth (LI_I32BLOCK (ls, _, rest), d, max_depth)
                            =>
                            depth (rest, d+1, int::max (max_depth, d+length ls));
                    end;

                    fun put_lit_expression (dictionary, expression, code)
                        =
                        case expression
                            #
                            (LI_TOP ls)                      =>   put_return ! emitablock (LI_RECORD, ls, code);
                            #
                            (LI_BLOCK (bk, ls, v, rest)) =>   put_lit_expression (v ! dictionary, rest, emitablock (bk, ls, code));
                            (LI_F64BLOCK  (ls, v, rest)) =>   put_lit_expression (v ! dictionary, rest, put_f64block  (ls, code));
                            (LI_I32BLOCK  (ls, v, rest)) =>   put_lit_expression (v ! dictionary, rest, put_i32block  (ls, code));
                        esac
                        where
                            fun put_lit_vals ([], _, code)
                                    =>
                                    code;

                                put_lit_vals (lit ! r, d, code)
                                    =>
                                    {
                                        instruction
                                            =
                                            case lit
                                                (LI_INT i) => put_int i;
                                                (LI_STRING s) => put_string s;

                                                (LI_VAR v)
                                                    =>
                                                    put_lit (f (dictionary, d))
                                                    where
                                                        fun f ([], _) => bug "unbound ncf::Codetemp";
                                                            f (v' ! r, d) => if (v == v')  d; else f (r, d+1);fi;
                                                        end;
                                                    end;
                                            esac;


                                        put_lit_vals (r, d+1, instruction ! code);
                                    };
                            end;

                            fun emitablock (LI_RECORD, ls, code)
                                    =>
                                    put_record (length ls) ! put_lit_vals (ls, 0, code);

                                emitablock (LI_VECTOR, ls, code)
                                    =>
                                    put_vector (length ls) ! put_lit_vals (ls, 0, code);
                            end;

                            fun put_f64block (ls, code)
                                =
                                put_raw64 (map ieee_float_constants::realconst ls) ! code;

                            fun put_i32block (ls, code)
                                =
                                put_raw32 ls ! code;

                        end;                                    # fun put_lit_expression

              end;
        end;


        ############################################################################
        #                    Lifting literals on highcode
        ############################################################################


        #  fun liftlits body = bug "highcode version currently not implemented yet"
        #  
        #  fun split_off_nextcode_literals (FK_FCT, f, [(v, t)], body) = 
        #        if lt::uniqtypoid_is_package t then
        #          let my (nbody, lit, llt) = liftlits body
        #              nt = lt::make_package_uniqtypoid ((lt::unpack_package_uniqtypoid t)@[llt])
        #           in ((FK_FCT, f, [(v, nt)], body), lit)
        #          end
        #        else bug "unexpected highcode header in split_off_nextcode_literals (case 1)"
        #    | split_off_nextcode_literals _ = bug "unexpected highcode header in split_off_nextcode_literals (case 2)"



        ############################################################################
        #                    Lifting literal on nextcode
        ############################################################################

        Info 
          = ZZ_STRING  String
          | ZZ_FLOAT   String
          | ZZ_RECORD  (ncf::Record_Kind, List( ncf::Value ))
          ;

        exception LITERAL_INFO;

        Rlit = RLIT  (String, Unt);


        fun to_rlit s
            =
            RLIT (s, hash_string::hash_string s);


        fun from_rlit (RLIT (s, _))
            =
            s;


        fun rlitcmp (RLIT (s1, i1), RLIT (s2, i2))
            = 
            if   (i1 < i2)  LESS;
            elif (i1 > i2)  GREATER;
            else            string::compare (s1, s2);
            fi;


        package rlit_dictionary
            =
            red_black_map_g (
                Key = Rlit;
                compare = rlitcmp;
            );

        # Lifting all literals from a nextcode program:
        #
        fun liftlits (body, root, offset)
            = 
            {   # The list of record, string, or float constants 
                #
                my m:  iht::Hashtable(Info) = iht::make_hashtable  { size_hint => 32,  not_found_exception => LITERAL_INFO };
                my freevars:    Ref( List( ncf::Codetemp ) ) = REF [];

                fun addv x = (freevars := (x ! *freevars));

                # Check if a ncf::Codetemp is used by the main program 
                #       
                my refset:   intset::Intset          =   intset::new();
                my used:     ncf::Codetemp -> Void   =   intset::add refset; 
                my is_used:  ncf::Codetemp -> Bool   =   intset::mem refset;

                #  memoize the information on which corresponds to what 

                fun enter (v, i)
                    =
                    {   iht::set m (v, i);
                        addv v;
                    };

                fun const (ncf::CODETEMP v)                                            =>  ({ iht::get  m  v; TRUE;} except _ = FALSE);
                    const (ncf::INT _ | ncf::INT1 _ | ncf::FLOAT64 _ | ncf::STRING _) =>  TRUE;
                    const _                                                            =>  bug "unexpected case in const";
                end;

                fun cstlit (ncf::CODETEMP v)                =>  ({ iht::get  m  v; TRUE;} except _ = FALSE);
                    cstlit (ncf::FLOAT64 _ | ncf::STRING _) =>  TRUE;
                    cstlit _                                =>  FALSE;
                end;

                # Register a string literal:
                #
                stipulate

                    my strs:     Ref( List( String ) )  =  REF [];
                    my strs_n:   Ref( Int )             =  REF 0;

                    sdict  =   REF (rlit_dictionary::empty);
                    srtv   =   make_var();
                    srtval =   ncf::CODETEMP srtv;

                herein

                    fun typechecked_package_string  s
                        = 
                        {   v = make_var();             # Should hash to remove duplicates      XXX BUGGO FIXME
                            sd = *sdict;
                            rlit = to_rlit s;

                            n = 
                                case (rlit_dictionary::get (sd, rlit))
                                    #
                                    THE k => k;
                                    #
                                    _ => { (strs := (s ! *strs));
                                            k = *strs_n;
                                            (strs_n := (k+1)); 
                                            (sdict := (rlit_dictionary::set (sd, rlit, k)));
                                          k;
                                        };
                                esac;

                            ( ncf::CODETEMP v,
                              \\ next =  ncf::GET_FIELD_I { i       =>  n,
                                                            record  =>  srtval,
                                                            to_temp =>  v,
                                                            type    =>  ncf::bogus_pointer_type,
                                                            next
                                                          }
                            );
                        };

        #       old definition of typechecked_package_string
        #
        #             let sd = *sdict
        #                 rlit = toRlit s
        #              in (case RlitDict::peek (sd, rlit)
        #                   of THE v => (ncf::CODETEMP v, ident)
        #                    | _ => let v = make_var()
        #                               (enter (v, ZZ_STRING s); used v)
        #                               (sdict := RlitDict::set (sd, rlit, v))
        #                            in (ncf::CODETEMP v, ident)
        #                           end)
        #             end


                    fun apply_package ()
                        =
                        {   fun g (a ! r, z) =>  g (r, (ncf::STRING a) ! z);  
                                g ([],    z) =>  z;                      # Reverse to get correct order.
                            end;

                            all_strs = *strs;

                            case *strs

                                 [] => ();
                                 xs => {   enter (srtv, ZZ_RECORD (ncf::rk::RECORD, g (xs,[])));
                                           used srtv;
                                       };
                            esac;
                      };
                end;                    # stipulate

                # * a special treatment of float constants 
                stipulate

                      my floats:    Ref( List( String ) ) = REF [];
                      my floats_n:  Ref( Int ) = REF 0;

                      rdict  =  REF (rlit_dictionary::empty);
                      rrtv   =  make_var();
                      rrtval =  ncf::CODETEMP rrtv;

                herein                                 

                    fun typechecked_package_float s
                        = 
                        {   v    = make_var();          # Should hash to remove duplicates XXX BUGGO FIXME
                            rd   = *rdict;

                            rlit = to_rlit s;

                            n    = case (rlit_dictionary::get (rd, rlit))
                                         THE k => k;
                                         _     => {   floats := (s ! *floats);
                                                      k = *floats_n;
                                                      floats_n := (k+1);
                                                      rdict := (rlit_dictionary::set (rd, rlit, k));
                                                      k;
                                                  };
                                   esac;


                            ( ncf::CODETEMP v,
                              \\ next = ncf::GET_FIELD_I  { i       =>  n,
                                                            record  =>  rrtval,
                                                            to_temp =>  v,
                                                            type    =>  ncf::typ::FLOAT64,
                                                            next
                                                          }
                            );
                        };

                    fun apply_float ()
                        = 
                        {   fun g (a ! r, z) => g (r, (ncf::FLOAT64 a) ! z);  
                                g (   [], z) => z;                              #  reverse to reflecting the correct order 
                            end;

                            all_floats = *floats;

                            case *floats 
                                [] => ();
                                xs => {   enter (rrtv, ZZ_RECORD (ncf::rk::FLOAT64_BLOCK, g (xs,[])));
                                          used rrtv;
                                      };
                            esac;
                        };

                end;                            # stipulate of special treatment of float constants 

                # Translation on the nextcode values:
                #
                fun lpsv u
                   = 
                   case u
                       #
                       ncf::FLOAT64 s =>   typechecked_package_float    s;
                       ncf::STRING  s =>   typechecked_package_string  s;
                       #
                       ncf::CODETEMP     v =>   { used v; (u, ident);};
                       _              =>   (u, ident);
                   esac;

                fun lpvs vs
                    = 
                    fold_backward g ([], ident) vs
                    where
                        fun g (u, (xs, hh))
                            = 
                            { my (nu, nh) = lpsv u; 
                              (nu ! xs, nh o hh); 
                            };
                    end;

                #  If all fields of a record are "constant", then we lift it:
                # 
                fun field' ul
                    = 
                    h (ul, [], FALSE)
                    where
                        fun h ((x, ncf::SLOT 0) ! r, z, rsflag)
                                => 
                                if (const x ) h (r, x ! z, rsflag or (cstlit x)); else NULL;fi;

                            h ([], z, rsflag) => if rsflag  THE (reverse z); else NULL;fi;
                            h _ => bug "unexpected case in field";
                        end;
                    end;

                #  Register a constant record:
                # 
                fun record (kind, ul, to_temp)
                    =
                    case (field' ul)

                        THE xl
                            =>
                            {   enter (to_temp, ZZ_RECORD (kind, xl));
                                ident;
                            };

                        NULL =>
                            {   fun g ((u, p as ncf::SLOT 0), (r, hh))
                                    => 
                                    {   my (nu, nh) = lpsv u;
                                        ((nu, p) ! r, nh o hh);
                                    };

                                    g _ => bug "unexpected non-zero ncf::SLOT in record";
                                end;

                                (fold_backward g ([], ident) ul) ->   (fields, header);

                                \\ next = header (ncf::DEFINE_RECORD { kind, fields, to_temp, next });
                            };
                    esac;

                # Register a wrapped float literal:
                #
                fun wrapfloat (u, to_temp, type)
                    = 
                    if (const u)
                        #
                        enter (to_temp, ZZ_RECORD (ncf::rk::FLOAT64_BLOCK, [u]));
                        ident;
                    else 
                        (lpsv u) ->   (nu, hh);
                        #
                        \\ next = hh (ncf::PURE { op   =>  ncf::p::WRAP_FLOAT64,
                                                  args =>  [nu],
                                                  to_temp,
                                                  type,
                                                  next
                                                }
                                   );
                    fi;

                # Fetch literal information:
                #
                fun get_info ()
                    = 
                    {   apply_float ();         # Register all Floats  as a record.
                        apply_package ();       # Register all Strings as a record.

                        allvars =  *freevars;
                        exports =   list::filter  is_used  allvars;

                        toplit
                            = 
                            g (exports, [])
                            where
                                fun g ([], z)
                                        =>
                                        LI_TOP z;

                                    g (x ! r, z)
                                        => 
                                        case (iht::get  m  x)
                                            #
                                            ZZ_STRING s =>  g (r, (LI_STRING s) ! z);
                                            _           =>  g (r, (LI_VAR    x) ! z);
                                        esac;
                               end;
                            end;

                        fun make_literal (v, lit)
                            =
                            {   fun un_float (ncf::FLOAT64 s) =>  s;
                                    un_float _                =>  bug "unFLOAT";
                                end;

                                fun un_int1 (ncf::INT1 w) =>  w;
                                    un_int1 _              =>  bug "unINT1";
                                end;

                                case (iht::get  m  v)
                                    #
                                    (ZZ_FLOAT _)                # Float is wrapped.
                                        => 
                                        bug "currently we don't expect ZZ_FLOAT in make_literal";

                                    #  LI_F64BLOCK([s], v, lit) 
                                    (ZZ_STRING s)
                                        => 
                                        bug "currently we don't expect ZZ_STRING in make_literal";

                                    # Lit   --- or we could inline string:
                                    # 
                                    (ZZ_RECORD (ncf::rk::FLOAT64_BLOCK, values))
                                        =>
                                        LI_F64BLOCK (map un_float values, v, lit);

                                    (ZZ_RECORD (ncf::rk::INT1_BLOCK, values))
                                        =>
                                        LI_I32BLOCK (map un_int1 values, v, lit);

                                    (ZZ_RECORD (rk, values))
                                        => 
                                        LI_BLOCK (rk2bk rk, map value_to_liternal values, v, lit);
                                esac;
                            };

                        # Build up the literal package:
                        #
                        lit =  fold_forward  make_literal  toplit  allvars;

                        n = length exports;

                        header
                            = 
                            if (n == 0)
                                #
                                ident;
                            else
                                rv   =   make_var();
                                rval =   ncf::CODETEMP rv;
                                rhdr =   \\ next =  ncf::GET_FIELD_I  { i       =>  offset,
                                                                        record  =>  root,
                                                                        to_temp =>  rv,
                                                                        type    =>  ncf::typ::POINTER (ncf::RPT n),
                                                                        next
                                                                      };

                                fun make_header (v, (i, hh))
                                    = 
                                    {   nh =    case (iht::get  m  v)
                                                    #
                                                    (ZZ_RECORD (rk, vs))
                                                        =>
                                                        {   n = length vs;

                                                            type =  case rk 
                                                                        #
                                                                        ncf::rk::FLOAT64_BLOCK =>  ncf::typ::POINTER (ncf::FPT n);
                                                                        ncf::rk::VECTOR        =>  ncf::bogus_pointer_type;
                                                                        _                      =>  ncf::typ::POINTER (ncf::RPT n);
                                                                    esac;

                                                            \\ next =  ncf::GET_FIELD_I { i, record => rval, to_temp => v, type, next };
                                                        };

                                                    (ZZ_FLOAT _) => bug "ZZ_FLOAT in make_header";
                                                       # (\\ next = 
                                                       #         (ncf::GET_FIELD_I { i => i, record => rval,            to_temp => w, type => ncf::typ::POINTER (FPT 1), next =>
                                                       #          ncf::GET_FIELD_I { i => 0, record => ncf::CODETEMP w, to_temp => v, type => FLTT, next } } ) )

                                                    (ZZ_STRING s) => bug "ZZ_STRING in make_header";
                                                       # (\\ next =
                                                       #          ncf::GET_FIELD_I { i, record => rval, to_temp => v, type => ncf::bogus_pointer_type, next } )
                                                esac;

                                        (i+1, hh o nh);
                                    };

                                #2 (fold_backward make_header (0, rhdr) exports);
                            fi;

                        (lit, header);
                    };                                  # fun get_info 

                fun lpfn (fk, f, vl, cl, e)             # "lpfn" may be "loop_fn"...?
                    =
                    (fk, f, vl, cl, loop e)

                also
                fun loop ce
                    =
                    case  ce
                        #
                        ncf::DEFINE_RECORD { kind, fields, to_temp,       next }
                            =>      record ( kind, fields, to_temp) (loop next);

                        ncf::GET_FIELD_I { i, record, to_temp, type, next }
                            => 
                            {   (lpsv record) ->   (record, hh);
                                #
                                hh (ncf::GET_FIELD_I { i, record, to_temp, type, next => loop next });
                            };

                        ncf::GET_ADDRESS_OF_FIELD_I _ => bug "unexpected ncf::GET_ADDRESS_OF_FIELD_I in loop";

                        ncf::TAIL_CALL { fn, args }
                            => 
                            {   (lpsv fn) ->   (fn, h1);
                                (lpvs args) ->   (args, h2);
                                #
                                h1 (h2 (ncf::TAIL_CALL { fn, args }));
                            };

                        ncf::DEFINE_FUNS { funs, next }
                            =>
                            ncf::DEFINE_FUNS  { funs =>  map lpfn funs,
                                                next =>  loop next
                                              };

                        ncf::JUMPTABLE { i, xvar, nexts }
                            => 
                            {   (lpsv i) ->   (i, hh);
                                hh (ncf::JUMPTABLE { i, xvar, nexts => map loop nexts });
                            };

                        ncf::IF_THEN_ELSE { op, args, xvar, then_next, else_next }
                            => 
                            {   (lpvs args) ->   (args, hh);
                                #
                                hh (ncf::IF_THEN_ELSE { op, args, xvar, then_next => loop then_next, else_next => loop else_next });
                            };

                        ncf::STORE_TO_RAM { op, args, next }
                            => 
                            {   (lpvs args) ->   (args, hh);
                                #
                                hh (ncf::STORE_TO_RAM { op, args, next => loop next });
                            };

                        ncf::FETCH_FROM_RAM { op, args, to_temp, type, next }
                            =>
                            {   (lpvs args) ->   (args, hh);
                                #
                                hh (ncf::FETCH_FROM_RAM { op, args, to_temp, type, next => loop next });
                            };

                        ncf::ARITH { op, args, to_temp, type, next }
                            =>
                            {   (lpvs args) ->   (args, hh);
                                #
                                hh (ncf::ARITH { op, args, to_temp, type,  next => loop next  });
                            };

                        ncf::PURE { op   =>  ncf::p::WRAP_FLOAT64,
                                    args =>  [arg],
                                    to_temp,
                                    type,
                                    next
                                  }
                            =>
                            wrapfloat  (arg, to_temp, type)  (loop next);


                        ncf::PURE { op, args, to_temp, type, next }
                            => 
                            {   (lpvs args) ->   (args, hh);
                                #
                                hh (ncf::PURE { op, args, to_temp, type,  next => loop next  });
                            };

                        ncf::RAW_C_CALL { kind, cfun_name, cfun_type, args, to_ttemps, next }
                            =>
                            {   (lpvs args) ->   (args, hh);
                                #
                                hh (ncf::RAW_C_CALL { kind, cfun_name, cfun_type, args, to_ttemps,  next => loop next });
                            };
                    esac;

                    newbody = loop body;

                    my (lit, header) = get_info ();

                    (header newbody, lit);
          };


        # Main function:
        #
        fun split_off_nextcode_literals (fk, f, vl as [_, x], [cntt, t as ncf::typ::POINTER (ncf::RPT n)], body)
                => 
                {   nt =   ncf::typ::POINTER (ncf::RPT (n+1));
                    #
                    (liftlits (body, ncf::CODETEMP x, n))
                        ->
                        (nbody, lit);

                    ((fk, f, vl, [cntt, nt], nbody), lit);
                };

            split_off_nextcode_literals _
                =>
                bug "unexpected nextcode header in split_off_nextcode_literals";
        end;

    };                                                          # package make_nextcode_literals_bytecode_vector
end;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext