PreviousUpNext

15.4.94  src/app/makelib/paths/fileid.pkg

## Author: Matthias Blume (blume@kurims.kyoto-u.ac.jp)

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

# Abstract file IDs.
#   - IDs for files regardless whether they exist or not.
#   - For existing files equivalent to winix__premicrothread::file::file_id.
#


###                           "Real Programmers don't comment their code.
###                            It was hard to write; it should be hard to read."



api File_Id {

    Id;
    Key = Id;

    compare:  (Id, Id) -> Order;

    file_id:  String -> Id;

    canonical:  String -> String;
};

package file_id:   File_Id {            # File_Id       is from   src/app/makelib/paths/fileid.pkg
    #
    package f =  winix__premicrothread::file;           # winix__premicrothread is from   src/lib/std/winix--premicrothread.pkg
    package p =  winix__premicrothread::path;

    Id
        = PRESENT  f::File_Id
        | ABSENT   String;

    Key = Id;

    fun compare (PRESENT fid, PRESENT fid') =>  f::compare (fid, fid');
        compare (ABSENT _,    PRESENT _   ) =>  LESS;
        compare (PRESENT _,   ABSENT _    ) =>  GREATER;
        compare (ABSENT s,    ABSENT s'   ) =>  string::compare (s, s');
    end;

    fun file_id f
        =
        {   # To maximize our chances of recognizing
            # equivalent path names to non-existing files,
            # we use f::full_path to expand the largest
            # possible prefix of the path.

            fun expand_path f
                =
                {   fun loop { dir, file }
                        =
                        p::cat (f::full_path dir, file)
                        except
                            _
                            =
                            {   my { dir => dir', file => file' }
                                    =
                                    p::split_path_into_dir_and_file dir;
                            
                                loop {
                                    dir  =>  dir',
                                    file =>  p::cat (file', file)
                                };
                            };
                

                    # An initial call to split_path_into_dir_and_file
                    # is ok because we already know
                    # that the complete path does not
                    # refer to an existing file:

                    loop (p::split_path_into_dir_and_file f);
                };
        
            PRESENT (f::file_id f)
            except
                _ = ABSENT (expand_path f);
        };


    fun canonical ""
            =>
            "";
 
        canonical f
            =>
            if  (f::access (f, [])
                 except
                     _ = FALSE
            )
                 f' =  p::make_canonical f;

                 if   (f::compare (f::file_id f, f::file_id f')  ==  EQUAL)
                      f';
                 else f;  fi;
            else
                 my { dir, file }
                     =
                     p::split_path_into_dir_and_file f;

                 p::make_path_from_dir_and_file  { dir => canonical dir,  file };
            fi;
    end;
};


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext