PreviousUpNext

15.4.46  src/app/makelib/compilable/module-dependencies-summary-io.pkg

## module-dependencies-summary-io.pkg
## (C) 1999 Lucent Technologies, Bell Laboratories
## Author: Matthias Blume (blume@kurims.kyoto-u.ac.jp)

# Compiled by:
#     src/app/makelib/makelib.sublib



# Reading and writing module_dependencies_summarys to module_dependencies_summary files.
# Module_Dependencies_Summarys provide a quick summary of a file,
# often saving us from generating a full parsetree.
# Or that's the idea, anyhow.
#
# Our runtime calls are from (only)
#
#     src/app/makelib/compilable/thawedlib-tome.pkg


stipulate
    package mds =  module_dependencies_summary;                                                 # module_dependencies_summary           is from   src/app/makelib/compilable/module-dependencies-summary.pkg
    package ts  =  timestamp;                                                                   # timestamp                             is from   src/app/makelib/paths/timestamp.pkg
herein
    api Module_Dependencies_Summary_Io {
        #
        read:   (/*filename:*/String, ts::Timestamp)                   -> Null_Or( mds::Declaration );
        write:  (/*filename:*/String, mds::Declaration, ts::Timestamp) -> Void;
    };
end;

stipulate
    package fil =  file__premicrothread;                                                        # file__premicrothread                  is from   src/lib/std/src/posix/file--premicrothread.pkg
    package mds =  module_dependencies_summary;                                                 # module_dependencies_summary           is from   src/app/makelib/compilable/module-dependencies-summary.pkg
    package pkr =  pickler;                                                                     # pickler                               is from   src/lib/compiler/src/library/pickler.pkg
    package spp =  symbol_and_picklehash_pickling;                                              # symbol_and_picklehash_pickling        is from   src/lib/compiler/front/semantic/pickle/symbol-and-picklehash-pickling.pkg
    package syp =  symbol_path;                                                                 # symbol_path                           is from   src/lib/compiler/front/typer-stuff/basics/symbol-path.pkg
    package sys =  symbol_set;                                                                  # symbol_set                            is from   src/app/makelib/stuff/symbol-set.pkg
    package tag =  pickler_datatype_tags;                                                       # pickler_datatype_tags                 is from   src/lib/compiler/src/library/pickler-datatype-tags.pkg
    package upr =  unpickler;                                                                   # unpickler                             is from   src/lib/compiler/src/library/unpickler.pkg
herein

    package   module_dependencies_summary_io
    :         Module_Dependencies_Summary_Io                                                    # Module_Dependencies_Summary_Io        is from   src/app/makelib/compilable/module-dependencies-summary-io.pkg
    {
        exception FORMAT = upr::FORMAT;
        #
        s2b =  byte::string_to_bytes;                                                           # byte                                  is from   src/lib/std/src/byte.pkg
        b2s =  byte::bytes_to_string;
        b2c =  byte::byte_to_char;

        version = "Module_Dependencies_Summary 5\n";


        fun makeset l
            =
            sys::add_list (sys::empty, l);


        fun read_line stream
            =
            loop []
            where

                fun finish resultlist
                    =
                    string::implode  (reverse  resultlist);


                fun loop resultlist
                    =
                    case (null_or::map  b2c  (data_file__premicrothread::read_one  stream))
                        #
                        NULL     =>  finish ('\n' ! resultlist);
                        THE '\n' =>  finish ('\n' ! resultlist);
                        THE c    =>  loop (c ! resultlist);
                    esac;
            end;


        fun write_decl (s, d)
            =
            {
                wrap_symbol =  spp::wrap_symbol;

                wrap_list = pkr::wrap_list;

                mknod =    pkr::make_funtree_node   tag::symbol_path;


                fun wrap_symbol_path (syp::SYMBOL_PATH p)
                    =
                    mknod "p"  [wrap_list wrap_symbol p];


                fun wrap_declaration  arg
                    =
                    d arg
                    where 
                        mknod =   pkr::make_funtree_node   tag::mds_declaration;
                        #
                        fun d (mds::BIND (name, def)) =>   mknod "a"  [wrap_symbol name, wrap_module_expression def];
                            d (mds::LOCAL (x, y))     =>   mknod "b"  [wrap_declaration x, wrap_declaration y];
                            d (mds::PAR l)            =>   mknod "c"  [wrap_list wrap_declaration l];
                            d (mds::SEQ l)            =>   mknod "d"  [wrap_list wrap_declaration l];
                            d (mds::OPEN d)           =>   mknod "e"  [wrap_module_expression d];
                            d (mds::REF s)            =>   mknod "f"  [wrap_list wrap_symbol (sys::vals_list s)];
                        end;

                    end

                also
                fun wrap_module_expression arg
                    =
                    m arg
                    where 
                        mknod =   pkr::make_funtree_node   tag::mds_module_expression;
                        #
                        fun m (mds::VARIABLE p)    =>   mknod "g"  [wrap_symbol_path p];
                            m (mds::DECL d)        =>   mknod "h"  [wrap_list wrap_declaration d];
                            m (mds::LET (d, e))    =>   mknod "i"  [wrap_list wrap_declaration d, wrap_module_expression e];
                            m (mds::IGN1 (e1, e2)) =>   mknod "j"  [wrap_module_expression e1, wrap_module_expression e2];
                        end;
                    end;

                pickle = s2b (pkr::funtree_to_pickle () (wrap_declaration d));

                data_file__premicrothread::write (s, byte::string_to_bytes version);
                data_file__premicrothread::write (s, pickle);
            };
                                                                    # data_file__premicrothread is from   src/lib/std/src/posix/data-file--premicrothread.pkg

        fun read_decl s
            =
            {   first_line =  read_line s;

                unpickler =   upr::make_unpickler  (upr::make_charstream_for_string  (b2s  (data_file__premicrothread::read_all  s)));

                string =  upr::read_string  unpickler;
                symbol =  symbol_and_picklehash_unpickling::read_symbol (unpickler, string);

                fun list  sharemap  read_element
                    =
                    upr::read_list  unpickler  sharemap  read_element;

                fun read_sharable_value   sharemap  read_value
                    =
                    upr::read_sharable_value   unpickler   sharemap   read_value;

                symbol_path_sharemap            =  upr::make_sharemap ();
                symbol_list_m                   =  upr::make_sharemap ();
                declaration_sharemap            =  upr::make_sharemap ();
                decl_list_m                     =  upr::make_sharemap ();
                module_expression_sharemap      =  upr::make_sharemap ();

                symbollist
                    =
                    list  symbol_list_m  symbol;

                fun path ()
                    =
                    read_sharable_value  symbol_path_sharemap  p
                    where
                        fun p 'p' =>  syp::SYMBOL_PATH (symbollist ());
                            p _   =>  raise exception FORMAT;
                        end;
                    end;

                fun decl ()
                    =
                    read_sharable_value  declaration_sharemap  d
                    where
                        fun d 'a' =>  mds::BIND  (symbol (), module_expression ());
                            d 'b' =>  mds::LOCAL (decl (), decl ());
                            d 'c' =>  mds::PAR   (decllist ());
                            d 'd' =>  mds::SEQ   (decllist ());
                            d 'e' =>  mds::OPEN  (module_expression ());
                            d 'f' =>  mds::REF   (makeset (symbollist ()));
                            d _   =>  raise exception FORMAT;
                        end;
                    end

                also
                fun decllist ()
                    =
                    list  decl_list_m  decl  ()

                also
                fun module_expression ()
                    =
                    read_sharable_value  module_expression_sharemap  m
                    where 
                        fun m 'g' =>   mds::VARIABLE  (path ());
                            m 'h' =>   mds::DECL  (decllist ());
                            m 'i' =>   mds::LET   (decllist (),      module_expression ());
                            m 'j' =>   mds::IGN1  (module_expression (), module_expression ());

                            m _   =>   raise exception FORMAT;
                        end;
                    end;

                if (first_line != version)   raise exception FORMAT;    fi;
                     
                decl ();
            };


        fun read (s, timestamp)
            =
            if  (timestamp::needs_update
                     {
                       target => timestamp::last_file_modification_time  s,
                       source => timestamp
                     }
            )
                 NULL;
            else
                 THE (
                     safely::do {
                       open_it  =>  .{ data_file__premicrothread::open_for_read s; },
                       close_it =>  data_file__premicrothread::close_input,
                       cleanup  =>  fn _ = ()
                     }
                     read_decl
                 )
                 except
                     _ =  NULL;
            fi;

    # XXX BUGGO DELETEME
    fun abbreviate (full_pathname: String)
    =
    { root = "/pub/home/cynbe/src/mythryl/mythryl7/mythryl7.110.58/mythryl7.110.58";

    if   (string::is_prefix  root  full_pathname)

     "$ROOT"
     + 
     string::extract (full_pathname, string::length root, NULL);
    else
     full_pathname;
    fi;
    };
                                                    # timestamp                 is from   src/app/makelib/paths/timestamp.pkg
                                                    # safely                    is from   src/lib/std/safely.pkg
                                                    # data_file__premicrothread is from   src/lib/std/src/posix/data-file--premicrothread.pkg
                                                    # winix__premicrothread     is from   src/lib/std/winix--premicrothread.pkg
                                                    # file__premicrothread      is from   src/lib/std/src/posix/file--premicrothread.pkg
                                                    # autodir                   is from   src/app/makelib/stuff/autodir.pkg

        fun make_temporary_filename  filename
            =
            {   # Voice of Experience: During a parallel compile,
                # multiple versions of the compiler may be writing
                # the same module_dependencies_summary file at the same time, which
                # can result in a crash trying to set the timestamp
                # (below).
                #
                # To avoid that, we create the module_dependencies_summary file under
                # a private temporary name, then set its timestamp,
                # and only then rename it to its final name -- that
                # being an atomic operation not subject to race
                # conditions:
                #
                pid =  winix__premicrothread::process::get_process_id ();
                include sfprintf;
                pid =  sprintf' "%d" [ INT pid ];

                temporary_filename = filename + "." + pid + ".tmp";

                temporary_filename;
            };

        fun write (filename, sk, timestamp)
            =
            {   temporary_filename
                    =
                    make_temporary_filename  filename;

                fun cleanup _
                    =
                    {   winix__premicrothread::file::remove_file  temporary_filename
                        except
                            _ = ();

                        fil::say .{ cat ["[writing ", temporary_filename, " failed]\n"]; };
                    };

                safely::do
                    {
                      open_it  =>  .{ autodir::open_binary_output  temporary_filename; },
                      close_it =>  data_file__premicrothread::close_output,
                      cleanup
                    }
                   .{ write_decl (#stream, sk); };

                timestamp::set_last_file_modification_time  (temporary_filename, timestamp);

                winix__premicrothread::file::rename_file
                    {
                      from =>  temporary_filename,
                      to   =>  filename
                    };
            };
    };
end;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext