PreviousUpNext

15.4.86  src/app/makelib/mythryl-compiler-compiler/mythryl-compiler-compiler-g.pkg

## mythryl-compiler-compiler-g.pkg

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



# Here we define a special app which 'make's
# the compiler itself, a task which presents
# special-case problems such as bootstrapping
# a valid initial runtime state from nothing.
#
# (To 'make' any Mythryl program other than the
# compiler, we use the
#     src/app/makelib/main/makelib-g.pkg
# app.)
#
#
#
# In this file, we do essentially the following:
#
#
#  1)   Parse the "primordial" library specfile
#
#           src/lib/core/init/init.cmi
#
#       by calling
#
#           process_mythryl_primordial_library          from  src/app/makelib/mythryl-compiler-compiler/process-mythryl-primordial-library.pkg
#       
#       init.cmi has a special syntax and defines
#       various life-critical things like TRUE that
#       must be in place before vanilla .lib file
#       processing can take place.
#
#
#  2)   Compile the primordial library if a usable
#       freezefile is not already available for it.
#
#
#  3)   Load the primordial library into memory.
#
#
#  4)   Call
#
#           parse_libfile_tree_and_return_interlibrary_dependency_graph
#       from
#           src/app/makelib/parse/libfile-parser-g.pkg
#
#       on the compiler's root .lib file
#
#           src/etc/mythryl-compiler-root.lib
#
#       (which then recursively runs all
#       the other .lib files in the compiler)
#       to ensure that all the libraries
#       which are to be linked into the
#
#           bin/mythryld
#
#       "executable" heap image are up to date.
#
#       In the usual   lone_primary   case we pass this
#       function a FREEZE_ALL arg which forces it to make
#       .frozen freezefiles for all (real) libraries lacking them,
#       which in turn forces all .pkg and .api sourcefiles to
#       compile if they have not already done so.
#
#       In the (common) limiting case this requires
#       recompiling all the relevant .api and .pkg
#       sourcefiles and packing the resulting .compiled
#       files into .frozen library freezefiles.
#
#
#  5)   Write out two diskfiles named
#
#           COMPILED_FILES_TO_LOAD
#           LIBRARY_CONTENTS
#
#       containing all the information needed to
#       link the compiler libraries together to
#       form the   bin/mythryld   "executable".
#
#       Later, the
#
#           sh/make-compiler-executable
#
#       script will hand the above two files to
#
#           bin/mythryl-runtime-intel32
#
#       to generate the actual   bin/mythryld
#       "executable" heap image, but that is
#       outside of our purview;  we are just
#       a subroutine invoked by the
#
#           sh/make-compiler-libraries
#
#       script.
#
#
#  (mythryl-compiler-compiler-g.pkg also contains a fair amount
#  of non-working code intended to support parallel
#  and distributed compiles, which probably should be
#  ripped out and rewritten from scratch.   XXX BUGGO FIXME.) 
#
#
#     [ At some point we should tweak the code to hide the
#       special-case kludging around here from the user,
#       so that at the command-line level, compiling and
#       linking the compiler looks just like compiling
#       and linking any other program. XXX BUGGO FIXME. ]
#
#
#
# Api:
#
#     We get sealed as  Mythryl_Compiler_Compiler                       # Mythryl_Compiler_Compiler     is from   src/lib/core/internal/mythryl-compiler-compiler.api
#
#
#
# Generic invocation context:
#
#     The generic we define is invoked in
#
#         src/lib/core/mythryl-compiler-compiler/mythryl-compiler-compiler-for-intel32-posix.pkg
#
#     to define mythryl_compiler_compiler_for_intel32_posix -- the other platforms
#     define similar platform-specific backends.
#
#     One of these gets defined as make_compiler (the default
#     bootstrap compiler) via conditional inclusion in
#
#         src/lib/core/mythryl-compiler-compiler/mythryl-compiler-compiler-for-this-platform.lib
#
#     which gets invoked by sh/make-compiler-libraries
#     which gets invoked by a toplevel 'make compiler'
#
#
#
# Generic arguments:
#
#     "mythryl_compiler" is defined by
#
#             package mythryl_compiler = mythryl_compiler_for_intel32_posix;
#         in
#             src/lib/compiler/toplevel/compiler/mythryl-compiler-for-intel32-posix.pkg
#
#         which gets conditionally included by
#
#             src/lib/core/compiler/mythryl-compiler-for-this-platform.lib
#
#         (The above is for "intel32-linux" platforms:
#         The pattern is similar on other platforms.)
#
#     "read_eval_print_from_stream" is backend::interact::read_eval_print_from_stream
#         which read_eval_print_loops_g defines in
#
#             src/lib/compiler/toplevel/interact/read-eval-print-loops-g.pkg
#
#         as a simple wrapper around the read_eval_print_from_stream
#         function defined by read_eval_print_loop_g in
#
#             src/lib/compiler/toplevel/interact/read-eval-print-loop-g.pkg
#     
#
# Runtime invocation context:
#
#     One path is via
#         src/lib/core/internal/make-mythryld-executable.pkg                    "make_mythryl_compiler_etc::make_compiler_etc root_directory"
#         src/lib/core/internal/make-mythryl-compiler-etc.pkg         make_compiler::make_compiler' (...)
#
#     The most usual invocation is via a manual linux commandline
#             "make compiler"   
#             Makefile ->
#                 sh/make-compiler-libraries
#         which first constructs the bootstrap compiler by running mythryld on
#             src/lib/core/compiler/mythryl-compiler-for-this-platform.lib
#         and then invokes it via a script-embedded
#             make_compiler::make_compiler ()
#
#     Either way, we quickly wind up at make_compiler'()
#     at the bottom of this file, and away we go.

stipulate
    package err =  error_message;                                                       # error_message                                 is from   src/lib/compiler/front/basics/errormsg/error-message.pkg
    package fil =  file__premicrothread;                                                # file__premicrothread                          is from   src/lib/std/src/posix/file--premicrothread.pkg
    package fzp =  freeze_policy;                                                       # freeze_policy                                 is from   src/app/makelib/parse/freeze-policy.pkg
    package flt =  frozenlib_tome;                                                      # frozenlib_tome                                is from   src/app/makelib/freezefile/frozenlib-tome.pkg
    package frn =  find_reachable_sml_nodes;                                            # find_reachable_sml_nodes                      is from   src/app/makelib/depend/find-reachable-sml-nodes.pkg
    package fts =  frozenlib_tome_set;                                                  # frozenlib_tome_set                            is from   src/app/makelib/freezefile/frozenlib-tome-set.pkg
    package lg  =  inter_library_dependency_graph;                                      # inter_library_dependency_graph                is from   src/app/makelib/depend/inter-library-dependency-graph.pkg
    package log =  logger;                                                              # logger                                        is from   src/lib/src/lib/thread-kit/src/lib/logger.pkg
    package lsi =  library_source_index;                                                # library_source_index                          is from   src/app/makelib/stuff/library-source-index.pkg
    package mcc =  mythryl_compiler_compiler_configuration;                             # mythryl_compiler_compiler_configuration       is from   src/app/makelib/mythryl-compiler-compiler/mythryl-compiler-compiler-configuration.pkg
    package md  =  makelib_defaults;                                                    # makelib_defaults                              is from   src/app/makelib/stuff/makelib-defaults.pkg
    package mtq =  makelib_thread_boss;                                                 # makelib_thread_boss                           is from   src/app/makelib/concurrency/makelib-thread-boss.pkg
    package ms  =  makelib_state;                                                       # makelib_state                                 is from   src/app/makelib/main/makelib-state.pkg
    package pl  =  process_mythryl_primordial_library;                                  # process_mythryl_primordial_library            is from   src/app/makelib/mythryl-compiler-compiler/process-mythryl-primordial-library.pkg
    package sa  =  supported_architectures;                                             # supported_architectures                       is from   src/lib/compiler/front/basics/main/supported-architectures.pkg
    package sg  =  intra_library_dependency_graph;                                      # intra_library_dependency_graph                is from   src/app/makelib/depend/intra-library-dependency-graph.pkg
    package spm =  source_path_map;                                                     # source_path_map                               is from   src/app/makelib/paths/source-path-map.pkg
    #
    find_set_of_compiled_files_for_executable
        =
        find_set_of_compiled_files_for_executable::find_set_of_compiled_files_for_executable;


    # Logging support.  To log messages from this file scatter
    #
    #     to_log {. sprintf "Whatever"; };                                              # Do not add trailing newline to message string.
    #
    # calls through the code as appropriate and then either
    # uncomment the below
    #
    #     my _ = log::enable  compiler_compiler_logging;
    #
    # line or do
    #
    #     logger::enable  (the (logger::find_logtree_node_by_name "compiler_compiler::logging"));
    #
    # from the Mythryl interactive prompt.
    #
    compiler_compiler_logging
        =
        log::make_logtree_leaf
          { parent  =>  fil::all_logging,
            name    =>  "compiler_compiler::logging",
            default =>  TRUE                                                            # Change to TRUE or call  (log::enable compiler_compiler_logging)   to enable logging in this file.
          };
    #
    to_log =  log::log_if  compiler_compiler_logging  0;
herein


                                                                                        # find_set_of_compiled_files_for_executable     is from   src/app/makelib/mythryl-compiler-compiler/find-set-of-compiledfiles-for-executable.pkg
                                                                                        # mythryl_compiler_compiler_for_intel32_posix   is from   src/lib/core/mythryl-compiler-compiler/mythryl-compiler-compiler-for-intel32-posix.pkg
                                                                                        # anchor_dictionary                             is from   src/app/makelib/paths/anchor-dictionary.pkg
                                                                                        # lib7                                          is from   src/lib/std/lib7.pkg
                                                                                        # Mythryl_Compiler                              is from   src/lib/compiler/toplevel/compiler/mythryl-compiler.api

                                                                                        # os::Kind = POSIX | WIN32 | MACOS | OS2 | BEOS;
                                                                                        # for intel32-posix, 'mythryl_compiler' will be mythryl_compiler_for_intel32_posix, arriving
                                                                                        # via src/lib/core/mythryl-compiler-compiler/mythryl-compiler-compiler-for-intel32-posix.pkg

    generic package   mythryl_compiler_compiler_g   (
        #             ===========================
        #
        #                                                                               # mythryl_compiler_for_intel32_posix            is from   src/lib/compiler/toplevel/compiler/mythryl-compiler-for-intel32-posix.pkg
        #                                                                               # mythryl_compiler_for_intel32_win32            is from   src/lib/compiler/toplevel/compiler/mythryl-compiler-for-intel32-win32.pkg
        #                                                                               # mythryl_compiler_for_pwrpc32                  is from   src/lib/compiler/toplevel/compiler/mythryl-compiler-for-pwrpc32.pkg
        #                                                                               # mythryl_compiler_for_sparc32                  is from   src/lib/compiler/toplevel/compiler/mythryl-compiler-for-sparc32.pkg
        #                                                                               # Mythryl_Compiler                              is from   src/lib/compiler/toplevel/compiler/mythryl-compiler.api
        package mythryl_compiler:       Mythryl_Compiler;                               # We get the host architecture and abi from this.

        os_kind: platform_properties::os::Kind;

        # This is currently always
        #     makelib_internal::load_plugin;                                            # makelib_internal                              is from   src/lib/core/internal/makelib-internal.pkg
        #  -- I'm not sure if/why it needs to
        # be a parameter here:
        #
        load_plugin                                                                     # load_plugin                                   def in    src/app/makelib/main/makelib-g.pkg
            :
            anchor_dictionary::Path_Root -> String -> Bool;
    )
    {
        package myc =  mythryl_compiler;                                                # "myc" == "mythryl_compiler"

        # How to compile ascii source to executable binary:
        #
        read_eval_print_from_stream =  myc::rpl::read_eval_print_from_stream
                                    :  fil::Input_Stream -> Void;



        # Set up a little dictionary defining
        # half a dozen platform properties
        # like architecture ("intel32" or such):
        #
        package mps                                                                     # "mps" == "makelib preprocessor state"
            =
            makelib_preprocessor_state_g (
                #
                architecture    =  myc::target_architecture;                            # PWRPC32/SPARC32/INTEL32.
                os_kind         =  os_kind;
                abi_variant     =  myc::abi_variant;
            );


                                                                                        # makelib_preprocessor_state_g  is from   src/app/makelib/main/makelib-preprocessor-state-g.pkg
                                                                                        # winix__premicrothread         is from   src/lib/std/winix--premicrothread.pkg
                                                                                        # filename_policy               is from   src/app/makelib/main/filename-policy.pkg
                                                                                        # backend_index                 is from   src/app/makelib/mythryl-compiler-compiler/backend-index.pkg
        # Cross-platform file I/O:
        #
        package f =   winix__premicrothread::file;
        package p =   backend_index;


        package ad = anchor_dictionary;                                                 # anchor_dictionary             is from   src/app/makelib/paths/anchor-dictionary.pkg

        machine_architecture                                                            # PWRPC32/SPARC32/INTEL32.
            =
            myc::target_architecture;

        osname                                                                          # "posix"/"macos"/"win32"/...
            =
            filename_policy::os_kind_to_string   os_kind;

        platform                                                                        # 'platform' string is architecture plus OS, e.g. "intel32-posix"   XXX BUGGO FIXME should rename 'platform' to 'arch_os' or such -- clearer.
            =
            cat [ architecture_name,
                  "-",
                  osname
                ]
                where
                    architecture_name =  sa::architecture_name  machine_architecture;
                end;



        package ffr
            =
            freezefile_roster_g ();
                                                                                        # freezefile_roster_g                                   is from   src/app/makelib/freezefile/freezefile-roster-g.pkg

                                                                                        # anchor_dictionary                                     is from   src/app/makelib/paths/anchor-dictionary.pkg
        package cdo                                                                     # "cdo" == "compile_(in_)dependency_order".
            =
            compile_in_dependency_order_g (                                             # compile_in_dependency_order_g                         is from   src/app/makelib/compile/compile-in-dependency-order-g.pkg
                #
                package myc =  mythryl_compiler;                                        # "myc" == "mythryl_compiler".
                package ffr =  ffr;                                                     # "ffr" == "freezefile_roster".
                #
                read_eval_print_from_stream
                    =
                    read_eval_print_from_stream;
            );

        package t2c
            =
            thawedlib_tome__to__compiledfile__map_g (
                #
                architecture =   myc::target_architecture;                              # PWRPC32/SPARC32/INTEL32.
            );


                                                                                        # thawedlib_tome__to__compiledfile__map_g       is from   src/app/makelib/compile/thawedlib-tome--to--compiledfile-contents--map-g.pkg
                                                                                        # compile_in_dependency_order_g                 is from   src/app/makelib/compile/compile-in-dependency-order-g.pkg
        package fzf                                                                     # "fzf" == "freezefile".
            =
            freezefile_g (                                                              # freezefile_g                                  is from   src/app/makelib/freezefile/freezefile-g.pkg
                #
                architecture                                                            # PWRPC32/SPARC32/INTEL32.
                    =
                    myc::target_architecture;

                package ffr =  ffr;                                                     # "ffr" == "freezefile_roster".

                                                                                        # compile_in_dependency_order_g                 is from   src/app/makelib/compile/compile-in-dependency-order-g.pkg
                                                                                        # link_in_dependency_order_g                    is from   src/app/makelib/compile/link-in-dependency-order-g.pkg
                # A function which allows
                #
                #     fzf::save_freezefile
                #
                # to recompile any thawed real library
                # handed to it:
                #
                fun compile_library
                        #
                        (makelib_state:     ms::Makelib_State)
                        #
                        (root_library:      lg::Inter_Library_Dependency_Graph)
                    =
                    {
# printf "compile_library/AAA\n";
                        (t2c::make__thawedlib_tome__to__compiledfile__map ())
                            ->
                            { set__compiledfile__for__thawedlib_tome,
                              get__compiledfile__for__thawedlib_tome
                            };

                        fun dummy_thawedlib_tome_watcher _ _
                            =
                            ();

# printf "compile_library/BBB\n";
                        my  { compile_library_catalog_in_dependency_order, ... }
                            =
                            cdo::make_dependency_order_compile_fns
                              {
                                root_library,
                                #
                                maybe_drop_thawedlib_tome_from_linker_map
                                   => dummy_thawedlib_tome_watcher,
                                #
                                set__compiledfile__for__thawedlib_tome
                              };

# printf "compile_library/CCC: before call to compile_library_catalog_in_dependency_order\n";
result =
                        case (compile_library_catalog_in_dependency_order  makelib_state)
                            #
                            THE _ =>  THE get__compiledfile__for__thawedlib_tome;
                            NULL  =>  NULL;
                        esac;
# printf "compile_library/ZZZ: after call to  compile_library_catalog_in_dependency_order\n";
result;
                    };

                get_symbol_and_inlining_mapstacks
                    =
                    cdo::get_symbol_and_inlining_mapstacks;
            );

        package vff
            =
            verify_freezefile_g   (package freezefile = fzf;);


                                                                # verify_freezefile_g                   def in    src/app/makelib/freezefile/verify-freezefile-g.pkg
                                                                # libfile_parser_g                      def in    src/app/makelib/parse/libfile-parser-g.pkg
                                                                # winix__premicrothread                 is from   src/lib/std/winix--premicrothread.pkg
        package lfp
            =
            libfile_parser_g (
                #
                package freezefile        =  fzf;
                package freezefile_roster =  ffr;
                #
                fun pending ()         =  symbol_map::empty;
                #
                drop_stale_entries_from_compiler_and_linker_maps
                    =
                    cdo::drop_stale_entries_from_compiler_map;
            );

#        include package   freeze_policy;

        #
        fun list_compiled_files_to_load  dependency_graph_root
            =
            find_set_of_compiled_files_for_executable
                #
                filepath_to_string
                #
                dependency_graph_root

            where

                fun filepath_to_string  filepath
                    =
                    {
                        # Convert absolute paths to ROOT-relative ones.
                        #
                        # NB: These were nice relative paths until
                        # I started frigging around with anchors,
                        # presumably an upstream fix somewhere
                        # would restore the status quo ante and
                        # obviate this kludge:          XXX BUGGO FIXME
                        #
                        root = (the (ad::get_anchor (ad::dictionary, "ROOT"))) + "/";
                        #
                        filepath =  if (string::is_prefix  root  filepath)
                                        #
                                        string::extract (filepath, string::length_in_bytes root, NULL);
                                    else
                                        filepath;
                                    fi;

                        case (winix__premicrothread::path::from_string  filepath)
                            #
                            { disk_volume =>  "",
                              is_absolute =>  FALSE,
                              arcs        =>  arc1 ! arcn
                            }
                                =>
                                {   fun win32name ()
                                        =
                                        cat (   arc1 !
                                                   fold_backward
                                                       (\\ (a, r) =  "\\" ! a ! r)
                                                       []
                                                       arcn
                                               );

                                    case os_kind
                                        #
                                        platform_properties::os::WIN32
                                            =>
                                            win32name ();

                                        _   =>
                                            winix__premicrothread::path::to_string
                                              {
                                                is_absolute =>  FALSE,
                                                disk_volume =>  "",
                                                arcs        =>  arc1 ! arcn
                                              };
                                    esac;
                                };

                            _    =>
                                 raise exception DIE ("src/app/makelib/mythryl-compiler-compiler/mythryl-compiler-compiler-g.pkg/list_compiled_files_to_load/list_name: bad name: "  +  filepath);
                        esac;
                };


            end;                                                # fun list_compiled_files_to_load

                                                                # find_set_of_compiled_files_for_executable     is from   src/app/makelib/mythryl-compiler-compiler/find-set-of-compiledfiles-for-executable.pkg
                                                                # compile_in_dependency_order_g                 def in    src/app/makelib/compile/compile-in-dependency-order-g.pkg
                                                                # libfile_parser_g                              def in    src/app/makelib/parse/libfile-parser-g.pkg
                                                                # freezefile_roster_g                           def in    src/app/makelib/freezefile/freezefile-roster-g.pkg
                                                                # file__premicrothread                          is from   src/lib/std/src/posix/file--premicrothread.pkg
        #
        fun clear_internal_state ()
            =
            {   cdo::clear_state ();
                lfp::clear_state ();
                ffr::clear_state ();
            };


        stipulate
            #
            current_generated_filename_infix
                =
                REF NULL;                               # XXX BUGGO FIXME more icky thread-hostile embedded state :(
        herein

            fun reset_state_if_generated_filename_infix_changed
                    generated_filename_infix
                =
                case *current_generated_filename_infix
                    #
                    NULL =>     current_generated_filename_infix
                                    :=
                                    THE generated_filename_infix;
                    #
                    THE generated_filename_infix'
                        =>
                        if (generated_filename_infix != generated_filename_infix')
                            #   
                            fil::say {.
                               cat [   "                                          mythryl-compiler-compiler-g.pkg:  New generated_filename_infix is `",
                                       generated_filename_infix,
                                       "';   Resetting make_compiler state.]\n"
                                   ];
                            };

                            clear_internal_state ();

                            current_generated_filename_infix
                                :=
                                THE generated_filename_infix;
                        fi;
                esac;
        end;

        #
        fun make_compiler {
                primary,                                                        # TRUE iff we're in the primary makelib process, FALSE if we're in a compile server.
                libfile,                                                        # NULL for default (src/etc/mythryl-compiler-root.lib) else  THE libfile_path_as_a_string.
                null_or_generated_filename_infix                                # Normally NULL (defaulting to "");  if this is THE ".pwrpc32-macos", instead of "foo.pkg.compiled" we'll generate "foo.pkg.pwrpc32-macos.compiled".
            }                                                                   # Could also be used by the sh/make-fixpoint script to generate multiple generations of compiler.
            =
            {
                # 2007-12-02 CrT: We can probably get rid of the build_directory argument at this point.  XXX BUGGO FIXME

                generated_filename_infix
                    =
                    the_else (
                        null_or_generated_filename_infix,
                        mcc::default_generated_filename_infix                   #  "" 
                    );

                reset_state_if_generated_filename_infix_changed
                    #
                    generated_filename_infix;


                mythryl_primordial_library
                    =
                    mcc::mythryl_primordial_library;                            #  "$ROOT/src/lib/core/init/init.cmi"   


                mythryl_compiler_root_library_filename
                    =
                    mcc::mythryl_compiler_root_library_filename;                                        #  "$ROOT/src/etc/mythryl-compiler-root.lib" 
                    #
                    #
                    # In practice,   mythryl_compiler_root_library_filename   points to
                    #
                    #     src/etc/mythryl-compiler-root.lib
                    #
                    # which in turn is a trivial wrapper for
                    #
                    #     src/lib/core/internal/interactive-system.lib
                    #
                    # This is important because it is the
                    # core specification of the entire
                    # compiler executable image that we're
                    # building here. :)


                # Should we keep on compiling after
                # encountering our first syntax error?
                #
                keep_going_after_compile_errors
                    =
                    md::keep_going_after_compile_errors.get ();
                #
                compiled_files_to_load_filename                                 # "COMPILED_FILES_TO_LOAD" 
                    =
                    mcc::compiled_files_to_load_filename;
                #
                picklehash_map_filename  =  mcc::picklehash_map_filename;               # "LIBRARY_CONTENTS" 
                anchor_dictionary        =  ad::dictionary;                             # More icky thread-hostile global mutable state! (Except we never mutate it...) XXX BUGGO FIXME.

                ad::sync ();

                #
                fun make_standard_source_path  file_path
                    =
                    ad::from_standard  anchor_dictionary  file_path;


                mythryl_primordial_library
                    =
                    make_standard_source_path  mythryl_primordial_library;


                mythryl_compiler_root_library_filename
                    =
                    case libfile
                        #                     
                        THE filename =>  ad::decode   anchor_dictionary   filename;
                        NULL         =>  make_standard_source_path mythryl_compiler_root_library_filename;
                    esac;


                filename_policy = filename_policy::policy;

                #
                fun make_makelib_session { we_are_a_subprocess }
                  =
                    {   makelib_thread_boss = mtq::make_makelib_thread_boss ();
                        #
                        { find_makelib_preprocessor_symbol
                              =>
                              mps::find_makelib_preprocessor_symbol,
                          #
                          anchor_dictionary,
                          filename_policy,
                          platform,                             # 'platform' string is architecture plus OS, e.g. "intel32-linux" 
                          keep_going_after_compile_errors,
                          we_are_a_subprocess => REF we_are_a_subprocess,
                          makelib_thread_boss
                        };
                    };

                # The library_source_index essentially maps
                # filenames to superficial file contents
                # info -- line and column numbers etc:
                #
                library_source_index
                    =
                    lsi::make_library_source_index ();

                # Where to send error messages:
                #
                plaint_sink
                    =
                    err::default_plaint_sink ();


                # Build an initial makelib_state, so that we can
                # deal with the pervasive dictionary and friends...
                #
                makelib_state
                  =
                  { library_source_index,
                    plaint_sink,
                    makelib_session     =>  make_makelib_session { we_are_a_subprocess => FALSE },
                    #
                    timestamp_of_youngest_sourcefile_in_library    =>  REF timestamp::ancient           # Used to decide whether a library rebuild is needed, in   src/app/makelib/main/makelib-g.pkg
                  };

                #
                fun make_main_compile   { pervasive => pervasive_node, others, source_code }
                    =
                    {
                        fun recompile_primordial_library ()
                            =
                            {   compile_tome_tin_after_dependencies'
                                    =
                                    cdo::compile_tome_tin_after_dependencies ();

                                #
                                fun compile_tome_tin_after_dependencies'' compiledfile
                                    =
                                   the (compile_tome_tin_after_dependencies'  makelib_state  compiledfile);

                                pervasive
                                    =
                                    compile_tome_tin_after_dependencies''   pervasive_node;

                                #
                                fun rt2ie (node,  symbol_and_inlining_mapstacks:  sg::Tome_Compile_Result)
                                    =
                                    {   symbolmapstack
                                            =
                                            symbol_and_inlining_mapstacks.symbolmapstack_thunk ();


                                        my  (tome_symbolmapstack, make_domain)
                                            =
                                            symbolmapstack__to__tome_symbolmapstack::convert
                                                symbolmapstack;


                                        domain =   make_domain ();

                                        { domain,
                                          #
                                          ie     => { masked_tome_thunk =>   \\ () =  { exports_mask => NULL, tome_tin => node },
                                                      tome_symbolmapstack,
                                                      exports_mask   =>   domain
                                                    }:                                          lg::Fat_Tome
                                        };
                                    };
                                #
                                fun add_exports (compiledfile, exports)
                                    =
                                    {   my  { ie, domain }
                                            =
                                            rt2ie (compiledfile, compile_tome_tin_after_dependencies'' compiledfile);

                                        #
                                        fun insert_imports_exports (symbol, m)
                                            =
                                            symbol_map::set (m, symbol, ie);


                                        symbol_set::fold_forward
                                           insert_imports_exports
                                           exports
                                           domain;
                                    };
                                                                                # symbol_set            is from   src/app/makelib/stuff/symbol-set.pkg
                                                                                # symbol_map            is from   src/app/makelib/stuff/symbol-map.pkg
                                                                                # pervasive_symbol      is from   src/app/makelib/main/pervasive-symbol.pkg
                                special_exports
                                    =
                                    {   fun make_imports_exports (pervasive_node, pervasive)
                                            =
                                            .ie (rt2ie (pervasive_node, pervasive));


                                        symbol_map::set (
                                            symbol_map::empty,
                                            pervasive_symbol::pervasive_package_symbol,
                                            make_imports_exports
                                                (pervasive_node, pervasive)
                                        );
                                    };

                                exports
                                    =
                                    fold_forward
                                        add_exports
                                        special_exports
                                        others;

                                main_library
                                    =
                                    lg::MAIN_LIBRARY
                                      {
                                        makelib_version_intlist => NULL,
                                        #
                                        frozen_vs_thawed_stuff
                                            =>
                                            lg::THAWEDLIB_STUFF
                                              {
                                                sublibraries       =>  []
                                              }
                                    };

                                lg::LIBRARY
                                    {
                                      catalog             =>   exports,
                                      more                =>   main_library,
                                      libfile             =>   mythryl_primordial_library,
                                      sources             =>   spm::empty,   #  A hack -- sources never used for this library. 
                                      sublibraries        =>   []
                                    };
                                                                                # string_set            is from   src/lib/src/string-set.pkg
                                                                                # source_path_map       is from   src/app/makelib/paths/source-path-map.pkg

                            };                                                  # fun recompile_primordial_library   in   fun make_main_compile   in   fun make_compiler

                        # Just go and load the primordial makefile
                        # freezefile or signal failure:
                        #
                        fun load_primordial_library ()
                            =
                            case (fzf::load_freezefile
                                    #
                                    { get_library =>  \\ _ =  raise exception DIE "make_compiler: load_primordial_library",
                                      saw_errors  =>  REF FALSE
                                    }
                                    #
                                    ( makelib_state,
                                      mythryl_primordial_library
                                      , NULL    # 'version' info XXX BUGGO DELETEME
                                      , []      # MUSTDIE
                                  ) )

                                THE (g as lg::LIBRARY _ ) =>  THE g;
                                NULL                      =>  NULL;
                                THE lg::BAD_LIBRARY       =>  NULL;
                            esac;



                        # Don't try to load the primordial
                        # libfile's freezefile:
                        # Instead, recompile directly:
                        #
                        fun compile_primordial_library ()
                            =
                            {   # Function recompile_primordial_library
                                # will not use servers but since
                                # compile dagwalks invoke the scheduler
                                # anyway, we must still clear pending tasks
                                # when we hit an error or an interrupt:
                                #
                                primordial_library
                                    =
                                    recompile_primordial_library ();

                                freezefile_arg
                                    =
                                    {   library    =>  primordial_library,
                                        saw_errors =>  REF FALSE
                                        , renamings  =>  []     # MUSTDIE
                                    };
                                                                                # freezefile is defined above.  See also src/app/makelib/freezefile/freezefile-g.pkg
                                if (not primary)
                                    #
                                    primordial_library;
                                else
to_log {. sprintf "Calling fzf::save_freezefile -- compile_primordial_library in src/app/makelib/mythryl-compiler-compiler/mythryl-compiler-compiler-g.pkg"; };
result =
                                    case (fzf::save_freezefile  makelib_state  freezefile_arg)
                                        #
                                        THE primordial_library
                                            =>
                                            {   lfp::clear_state ();
                                                primordial_library;
                                            };

                                        NULL  =>  raise exception DIE "make_compiler: cannot build initial library";
                                    esac;
to_log {. sprintf "Done calling fzf::save_freezefile -- compile_primordial_library in src/app/makelib/mythryl-compiler-compiler/mythryl-compiler-compiler-g.pkg"; };
result;
                                fi;
                            };                  # fun compile_primordial_library   in   fun make_main_compile   in   fun make_compiler



                        # Try loading the primordial library from
                        # its freezefile if possible; recompile it
                        # if loading fails:
                        #
                        fun load_or_compile_primordial_library ()
                            =
                            case (load_primordial_library ())
                                #                             
                                THE g =>  g;
                                NULL  =>  compile_primordial_library ();
                            esac;



                        # Ok, now, based on "paranoid" and
                        # freezefile verification, call the
                        # appropriate function (s)
                        # to get the primordial library:
                        #
                        primordial_library
                            =
                            if (not primary)
                                #
                                the (load_primordial_library ());   #  Failure caught at the end. 
                            else 
                                export_nodes =  pervasive_node ! others;
                                verify_arg   =  (mythryl_primordial_library, export_nodes, [], source_path_set::empty, NULL);
                                em           =  frozenlib_tome_map::empty;

                                                                              # source_path_set                 is from   src/app/makelib/paths/source-path-set.pkg
                                                                              # frozenlib_tome_map              is from   src/app/makelib/freezefile/frozenlib-tome-map.pkg
                                                                              # verify_freezefile_g             is from   src/app/makelib/freezefile/verify-freezefile-g.pkg
                                                                              # library_source_index            is from   src/app/makelib/stuff/library-source-index.pkg

                                if (vff::verify'  makelib_state  em  verify_arg)
                                    #
                                    load_or_compile_primordial_library  ();
                                else        compile_primordial_library  ();
                                fi;
                            fi;

                        library_source_index
                            =
                            lsi::make_library_source_index ();

                        lsi::register
                            library_source_index
                            (mythryl_primordial_library,   source_code);


                        # 2007-12-02 CrT: All this 'server' stuff should be chopped.
                        #                 it has never been debugged, doesn't work,
                        #                 and the design is poor -- instead of having
                        #                 each server reconstruct the compiler state on
                        #                 its own, we should just fork() to create the
                        #                 compile servers.
                        #
                        #                 Ultimately it would be nice to
                        #                 just use hostthreads in-process, but we have
                        #                 to clean up a lot of global-variable idiocy
                        #                 to make that possible.

                        #
                        fun parse_arg_0  { we_are_a_subprocess }  { freeze_policy, paranoid }
                            =
                            { makelib_file_to_read     => mythryl_compiler_root_library_filename,       #  Primary .libi file -- src/etc/mythryl-compiler-root.lib
                              #
                              load_plugin,
                              library_source_index,

                              makelib_session         => make_makelib_session { we_are_a_subprocess },
                              freeze_policy,

                              primordial_library,
                              paranoid
                            };

                        parse_arg        =  parse_arg_0  { we_are_a_subprocess => FALSE };
                        server_parse_arg =  parse_arg_0  { we_are_a_subprocess => TRUE  };


                                                                                        # libfile_parser_g      def in    src/app/makelib/parse/libfile-parser-g.pkg

                        interlibrary_dependency_graph                                   # There's actually a makelib_state tucked in there as well.
                            =
                            if (not primary)
                                #
                                lfp::parse_libfile_tree_and_return_interlibrary_dependency_graph
                                    (
                                        server_parse_arg { freeze_policy => fzp::FREEZE_NONE, paranoid => FALSE }                #  Server case 
                                    );
                            else
                                lfp::parse_libfile_tree_and_return_interlibrary_dependency_graph
                                    (
                                        parse_arg  { freeze_policy => fzp::FREEZE_ALL,  paranoid => TRUE }
                                    );

                            fi;

                                                                                                # We're in   fun make_main_compile   in   fun make_compiler
                        case interlibrary_dependency_graph
                            #
                            NULL =>  NULL;                                                      # Couldn't parse .lib tree, so just give up.
                            #
                            THE (libfile_dependency_graph, makelib_state)
                                =>
                                {   # Write to disk the COMPILED_FILES_TO_LOAD
                                    # and LIBRARY_CONTENTS files.
                                    #
                                    # These tell bin/mythryl-runtime-intel32 how to build the
                                    # bin/mythryld "executable" heap image:
                                    #
print "Writing out COMPILED_FILES_TO_LOAD and LIBRARY_CONTENTS files -- mythryl-compiler-compiler-g.pkg\n";
                                    fun write__compiled_files_to_load__and__library_contents
                                            #
                                            ( libfile_dependency_graph,
                                              makelib_state
                                            )
                                        =
                                        {   (list_compiled_files_to_load  libfile_dependency_graph)
                                                ->
                                                { l => compiled_files_to_load,
                                                  ss
                                                };

                                            compiled_files_to_load
                                                =
                                                map  #2  compiled_files_to_load;


                                            stipulate

                                                frozen_libraries
                                                    =
                                                    frn::freezefiles_of  libfile_dependency_graph;

                                                #
                                                fun in_set bi
                                                    =
                                                    fts::member (ss, bi);
                                            herein
                                                frontiers
                                                    =
                                                    spm::map
                                                           (frn::frontier in_set)
                                                           frozen_libraries;
                                            end;

                                                                                               # file__premicrothread           is from   src/lib/std/src/posix/file--premicrothread.pkg
                                            # Generate the COMPILED_FILES_TO_LOAD file:
                                            # 
                                            fun write_compiled_files_to_load  output_stream
                                                =
                                                {   fun write_string  string
                                                        =
                                                        fil::write (output_stream,  string + "\n");

                                                    item_count
                                                        =
                                                        length  compiled_files_to_load;

                                                    #
                                                    fun maximum_length (string, n)
                                                        =
                                                        int::max (size string, n);


                                                    maximum_line_length
                                                        =
                                                        fold_forward
                                                            maximum_length
                                                            0
                                                            compiled_files_to_load;

                                                    apply  write_string  [
                                                        "# This file was built  by src/app/makelib/mythryl-compiler-compiler/mythryl-compiler-compiler-g.pkg: write_compiled_files_to_load",
                                                        "# for consumption by mythryl-runtime-intel32: src/c/main/load-compiledfiles.c: read_in_compiled_file_list__may_heapclean.",
                                                        "#",
                                                        "# It gives a list of .compiled files to be linked together to form a Lib7 executable (heap image).",
                                                        "#",
                                                        "# Each line after the header specifies one .compiled file to load.",
                                                        "#",
                                                        "# The lines are topogically sorted so that no .compiled file depends upon a later one.",
                                                        "#",
                                                        "# An .compiled file is specified as either a simple filename, or else as a",
                                                        "# FREEZEFILENAME@OFFSET: LIBRARY_DESCRIPTION triple giving the offset of the",
                                                        "# compiledfile image within some library file, where LIBRARY_DESCRIPTION in turn",
                                                        "# is a LIBFILE@OFFSET (SOURCEFILE) triple giving the makefile which created",
                                                        "# the library and the name of the source file which was compiled to produce",
                                                        "# the .compiled file.  (The second OFFSET is redundant with the first.)",
                                                        (cat ["FILES=",           int::to_string item_count]),
                                                        (cat ["MAX_LINE_LENGTH=", int::to_string maximum_line_length  ]),
                                                        ""
                                                    ];

                                                    apply  write_string  compiled_files_to_load;
                                                };                                              # fun write_compiled_files_to_load   in   fun write__compiled_files_to_load__and__library_contents   in   fun make_main_compile   in   fun make_compiler


                                            # Generate the LIBRARY_CONTENTS file:
                                            # 
                                            fun write_library_contents_file s
                                                =
                                                {   apply
                                                        (\\ text = fil::write (s, text))
                                                        [
                                                            "# This file lists the contents of each library in this directory tree.\n",
                                                            "# Each line lists the contents of one library.\n",
                                                            "#\n",
                                                            "# The first entry on each line is the name of\n",
                                                            "# the makelib file which generated the library.\n",
                                                            "#\n",
                                                            "# The remaining entries on each line are OFFSET: PICKLEHASH pairs\n",
                                                            "# representing .compiled files, where OFFSET is the byte offset\n",
                                                            "# of the compiledfile image within the library file, and PICKLEHASH\n",
                                                            "# is a 16-byte hash of that image, expressed as a 32-char hex string.\n",
                                                            "#\n",
                                                            "# This file was generated by src/app/makelib/mythryl-compiler-compiler/mythryl-compiler-compiler-g.pkg: write_library_contents_file.\n",
                                                            "# It will typically be read by src/app/makelib/main/makelib-g.pkg: read_picklehash_map.\n",
                                                            "# It is not really intended for human consumption. :)\n"
                                                        ];

                                                    spm::keyed_apply
                                                        (write_picklehash_line s)
                                                        frontiers;
                                                }
                                                where
                                                    fun write_picklehash_line s (p, set)
                                                        =
                                                        if (not (fts::is_empty  set))
                                                            #                                                        
                                                            fil::write (s, ad::encode p);
                                                            fts::apply  (write_picklehash s)  set;
                                                            fil::write (s, "\n");
                                                        fi
                                                        where
                                                            fun write_picklehash  s  (tome: flt::Frozenlib_Tome)
                                                                =
                                                                {   description =   flt::describe_frozenlib_tome  tome;

                                                                    compiledfile
                                                                        =
                                                                        t2c::get_compiledfile_from_freezefile {
                                                                            #
                                                                            freezefile_name =>  tome.freezefile_name,
                                                                            offset          =>  tome.byte_offset_in_freezefile,
                                                                            description
                                                                        };

                                                                                       # compiledfile   is from   src/lib/compiler/execution/compiledfile/compiledfile.pkg

                                                                    case (compiledfile::hash_of_pickled_exports  compiledfile)
                                                                        #
                                                                        NULL => ();
                                                                        #
                                                                        THE picklehash
                                                                            =>
                                                                            apply
                                                                                (\\ str =  fil::write (s, str))
                                                                                [   " ",
                                                                                    int::to_string  tome.byte_offset_in_freezefile,
                                                                                    ":",
                                                                                    picklehash::to_hex  picklehash
                                                                                ];
                                                                    esac;
                                                                                       # file__premicrothread           is from   src/lib/std/src/posix/file--premicrothread.pkg
                                                                                       # int                            is from   src/lib/std/int.pkg
                                                                                       # picklehash                     is from   src/lib/compiler/front/basics/map/picklehash.pkg
                                                                };
                                                        end; 
                                                end;                                    # fun write_library_contents_file   in   fun write__compiled_files_to_load__and__library_contents   in   fun make_main_compile   in   fun make_compiler

                                                                                       # autodir                        is from   src/app/makelib/stuff/autodir.pkg
                                                                                       # file__premicrothread                           is from   src/lib/std/src/posix/file--premicrothread.pkg

                                            safely::do
                                                { close_it =>  fil::close_output,
                                                  open_it  =>    {.  autodir::open_text_output          compiled_files_to_load_filename;  },
                                                  cleanup  =>  \\ _ = (winix__premicrothread::file::remove_file  compiled_files_to_load_filename
                                                                       except _ = ())
                                                }
                                                write_compiled_files_to_load;

                                            safely::do
                                                { close_it =>  fil::close_output,
                                                  open_it  =>    {.  autodir::open_text_output    picklehash_map_filename;   },
                                                  cleanup  =>  \\ _ =  (winix__premicrothread::file::remove_file  picklehash_map_filename
                                                                        except _ = ())
                                                }
                                                write_library_contents_file;


                                            TRUE;
                                        };                                              # fun write__compiled_files_to_load__and__library_contents   in   fun make_main_compile   in   fun make_compiler






                                    # Don't do another dagwalk
                                    # if this is a lone primary:
                                    #
                                    fun just_build_library ()
                                        =
                                        write__compiled_files_to_load__and__library_contents
                                            #
                                            ( libfile_dependency_graph,
                                              makelib_state
                                            );

                                    # The following thunk is executed
                                    # in primary process only;
                                    # compile servers just throw it away:
                                    #
                                    fun freeze ()
                                        =
                                        {   my { compile_all_fat_tomes_in_library_in_dependency_order, ... }
                                                =
                                                cdo::make_dependency_order_compile_fns
                                                  {
                                                    root_library                              =>  libfile_dependency_graph,
                                                    maybe_drop_thawedlib_tome_from_linker_map =>  \\ _ = \\ _ = (),
                                                    set__compiledfile__for__thawedlib_tome    =>  \\ _ = ()
                                                  };


                                            if (compile_all_fat_tomes_in_library_in_dependency_order  makelib_state)
                                                #
                                                cdo::clear_state ();
                                                freeze' ();
                                            else
                                                FALSE;
                                            fi;
                                        }
                                        where
                                            # Phase 2 (freezing):
                                            #
                                            fun freeze' ()
                                                =
                                                # Now we re-parse everything with freezing
                                                # turned on (and servers turned off):

                                                                                                # parse_libfile_tree_and_return_interlibrary_dependency_graph defined above.

                                                case    (lfp::parse_libfile_tree_and_return_interlibrary_dependency_graph
                                                            (
                                                                parse_arg  { freeze_policy => fzp::FREEZE_ALL,  paranoid => FALSE  }
                                                        )   )
                                                    #
                                                    NULL => FALSE;
                                                    #
                                                    THE (libfile_dependency_graph, makelib_state)
                                                        =>
                                                        write__compiled_files_to_load__and__library_contents
                                                            #
                                                            (libfile_dependency_graph, makelib_state);
                                                esac;
                                        end;


                                    THE (  ( libfile_dependency_graph,
                                             makelib_state,
                                             anchor_dictionary
                                           ),

                                           just_build_library
                                        );
                                };
                        esac;
                    }                                                                           # fun make_main_compile   in   fun make_compiler
                    except
                        # Catch any failure in runtime or any compiler server
                        # failure to load primordial_library library:
                        #
                        NULL_OR =  {   cdo::clear_state ();
                                       NULL;
                                   };
                                                                                                # compile_in_dependency_order_g         is from   src/app/makelib/compile/compile-in-dependency-order-g.pkg
                case (pl::process_mythryl_primordial_library
                         makelib_state
                         mythryl_primordial_library
                     )
                    #
                    THE x =>  make_main_compile  x;
                    NULL  =>  NULL;
                esac;
            };                                                                                  # fun make_compiler 

                                                                                                # freezefile_roster_g                   is from   src/app/makelib/freezefile/freezefile-roster-g.pkg
        fun make_mythryl_compiler'  null_or_generated_filename_infix                            # Normally NULL (defaulting to ""), might be (e.g.) THE ".pwrpc32-macos" when cross-compiling.
            =
            {   ffr::clear_state ();
                #
                case (make_compiler {
                          primary   =>  TRUE,                                                   # We're in the root makelib process, not in a secondary compile-server process.
                          libfile =>  NULL,                                                     # Use default root .lib file, normally   src/etc/mythryl-compiler-root.lib
                          null_or_generated_filename_infix                                      # Normally NULL (defaults to "");  if this is THE ".pwrpc32-macos", instead of "foo.pkg.compiled" we'll generate "foo.pkg.pwrpc32-macos.compiled".
                        }
                     )                                                                          # 'make fixpoint' successively sets it to (THE "build7-1"), (THE "build7-2")...
                    #
                    NULL => FALSE;
                    #
                    THE (_, thunk)
                        =>
                        thunk ();                                                               # == either  just_build_library()  or  freeze()  -- see above.
               esac;
            };


        # To take advantage of multiple cores/CPUs/workstations,
        # makelib can spawn and use multiple "compile server" processes,
        # allowing multiple compiles to take place in parallel.
        #
        # Rather than load all platform-specific backends into memory
        # at the start, these servers economize on memory by loading
        # them only as needed -- the logic to do this is in
        #
        #     src/app/makelib/mythryl-compiler-compiler/backend-per-platform.pkg
        #
        # In order to be useful, as they load these backends must
        # enter themselves into a dynamic registry so as to be
        # accessible to makelib proper.  That registry is implemented in
        #
        #     src/app/makelib/mythryl-compiler-compiler/backend-index.pkg
        #
        # and it is now time to enter ourself into it.
        #
        # First we define the function which the toplevel compile-server
        # logic will call to invoke us, then we enter it into the registry:
        #
        stipulate
                                                                                                # freezefile_roster_g           is from   src/app/makelib/freezefile/freezefile-roster-g.pkg
                                                                                                # makelib_preprocessor_state_g  is from   src/app/makelib/main/makelib-preprocessor-state-g.pkg
            fun backend_function  NULL
                     =>
                     {   clear_internal_state ();
                         NULL;
                     };

                backend_function
                        (THE
                            ( generated_filename_infix,                                         # Normally "";   if this is (e.g.) ".pwrpc32-macos", instead of "foo.pkg.compiled" we'll generate "foo.pkg.pwrpc32-macos.compiled".
                              libfile                                                           # 'libfile' string is .lib file to compile, in practice "src/etc/mythryl-compiler-root.lib" or "$ROOT/src/etc/mythryl-compiler-root.lib".
                        )   )
                    =>
                    {
                        ffr::clear_state ();

                        #   #define CMB_SERVER_MODE 1
                        #
                        (mps::find_makelib_preprocessor_symbol "CMB_SERVER_MODE").set           # This gets checked (only) in    src/lib/core/internal/lib7-version.lib
                            (THE 1);


                        case (  make_compiler
                                  {
                                    primary  =>  FALSE,                                         # We're running in a compile server process, not in the primary process.
                                    libfile  =>  THE libfile,
                                    #
                                    null_or_generated_filename_infix
                                        =>
                                        THE generated_filename_infix
                                   }
                             )
                            #                             
                            THE ((g, makelib_state, anchor_dictionary), _)
                                =>
                                {   compile_tome_tin_after_dependencies'
                                        =
                                        cdo::compile_tome_tin_after_dependencies ();
                                    #   
                                    fun compile_tome_tin_after_dependencies'' compiledfile
                                        =
                                        not_null (compile_tome_tin_after_dependencies'  makelib_state  compiledfile);

                                    THE (g, compile_tome_tin_after_dependencies'', anchor_dictionary);
                                };

                            NULL => NULL;
                         esac;
                     };
            end;
                                                                                                # compile_in_dependency_order_g                 is from   src/app/makelib/compile/compile-in-dependency-order-g.pkg
                                                                                                # backend_index                                 is from   src/app/makelib/mythryl-compiler-compiler/backend-index.pkg
                                                                                                # "p" is backend_index
        herein                                                          my _ =
            p::register_per_platform_backend_function
                platform
                backend_function;
        end;

        # Toplevel entrypoint for recompiling compiler; we arrive
        # here directly from   make_compiler::make_compiler ();  call in
        #     sh/make-compiler-libraries
        # which gets invoked by   compiler-libraries   case in
        #     Makefile
        # which gets invoked by   compiler             case in 
        #     Makefile
        # which we invoke by hand at the linux commandline.
        #
        fun make_mythryl_compiler ()
            =
            make_mythryl_compiler' NULL;                                                        # NULL is the   null_or_generated_filename_infix   arg.


        find_makelib_preprocessor_symbol
            =
            mps::find_makelib_preprocessor_symbol;
                                                                                                # makelib_preprocessor_state_g                  is from   src/app/makelib/main/makelib-preprocessor-state-g.pkg
    };

end;

## (C) 1999 Lucent Technologies, Bell Laboratories
## Author: Matthias Blume (blume@kurims.kyoto-u.ac.jp)
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2015,
## released per terms of SMLNJ-COPYRIGHT.


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext