PreviousUpNext

15.3.20  src/app/makelib/paths/anchor-dictionary.api

## anchor-dictionary.api -- Operations over abstract names for source files.

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

# Overview comments at bottom of file.        



###                                 "The lyf so short, the craft so long to lerne."
###
###                                                       --Geoffrey Chaucer



api Anchor_Dictionary {

    # We define an exception to raise if
    # we encounter an "impossible" byte
    # sequence while unpickling, presumably
    # as a result of diskfile corruption:
    #
    exception FORMAT;

    File;
    Path_Root;                                          # Root of a file path -- essentially, "/...",  "./..." or "$ROOT/..."
    Anchor_Dictionary;
    Anchor = String;
    Dir_Path;

    Renaming    =   { anchor: Anchor,   value:  Dir_Path   };   # MUSTDIE
    Renamings   =  List( Renaming );                            # MUSTDIE

    Key = File;


    compare:  (File, File) -> Order;                    # Compare paths for ordering 

    sync:            Void -> Void;                      # Re-establish stability of ordering. 
    clear:           Void -> Void;                      # Forget all known path names. 
    revalidate_cwd:  Void -> Void;                      # Re-validate current working directory. 

    add_cwd_watcher:  (String -> Void) -> Void;         # Register a "client" module that wishes 
                                                        # to be notified when the CWD changes.   
                                                        # Currently never called.

    # Make sure all such clients get notified
    # about the CWD during next validation:
    #
    schedule_notification:   Void -> Void;


    # A default dictionary containing
    # just the ROOT definition:
    #
    dictionary: Anchor_Dictionary;


    #  Destructive updates to anchor settings (for configuration) 
    #
    set_anchor:     (Anchor_Dictionary, Anchor,    Null_Or(String)) -> Void;              # Native host OS syntax! 
    get_anchor:     (Anchor_Dictionary, Anchor) -> Null_Or(String);

    print_anchors:  (Anchor_Dictionary, String) -> Void;

#   my keyvals_list:      Map(X) ->  List( key::Key * X )               src/lib/src/map.api
#   my listAnchorsi:    Anchor_Dictionary -> List( Anchor * String)     src/lib/src/ord-map.apk


    #  Make abstract paths: 

    # This is intended to support file_path args
    # in the local host OS notation -- even if it is Windows:
    #
    from_native:
        #
        { plaint_sink:  String -> Void }      #  Where to send error messages. 
        ->
        { path_root:    Path_Root,
          file_path:    String
        }
        ->
        Dir_Path;

    # This is intended to support file_path args
    # in our standard unix-like notation:
    #
    from_standard':
        #
        { plaint_sink:          String -> Void,                         # Where to send error messages. 
          anchor_dictionary:    Anchor_Dictionary
        }
        ->
        { path_root:            Path_Root,                              # Typically anchor_dictionary::cwd ().
          file_path:            String                                  # E.g. "$ROOT/src/lib/core/init/init.cmi"
        }                                                               # or   "$ROOT/src/lib/std/standard.lib"
        ->                                                              # or   "$ROOT/src/lib/core/mythryl-compiler-compiler/mythryl-compiler-compiler-for-this-platform.lib".
        Dir_Path;

    # A simplified version of the above
    # sufficient for most purposes:
    #
    from_standard:
        Anchor_Dictionary
        ->
        String /* filename */                                           # E.g. "$ROOT/src/lib/core/init/init.cmi"
        ->                                                              # or   "$ROOT/src/lib/std/standard.lib"
        File;                                                           # or   "$ROOT/src/lib/core/mythryl-compiler-compiler/mythryl-compiler-compiler-for-this-platform.lib".


    extend:   Dir_Path -> List(String) -> Dir_Path;
        #
        # Augment a basename (naming a directory) with a list of arcs.



    file:   Dir_Path -> File;
        #
        # Check that there is at least one arc (the actual filename!) after the path's path_root.

    file_to_basename:   File -> Dir_Path;
        #
        # To be able to pickle a file, turn it into a basename first... 


    # Directory paths (path_roots) 
    #
    current_working_directory:  Void -> Path_Root;
    #
    dir:  File -> Path_Root;

    # Get info out of abstract paths:
    #
    os_string:   File -> String;
    os_string' : File -> String;        #  Use relative path if shorter 

    abbreviate  : String -> String;     # Abbreviate any ROOT prefix

    # Get path relative to the file's path_root;
    # this will produce an absolute path if
    # the original file_path was not relative --
    # i.e., if it was anchored or absolute:
    #
    os_string_relative:  File -> String;

    # Same for basename:
    #
    os_string_basename_relative:  Dir_Path -> String;

    # Get name of path root:
    #
    os_string_dir:  Path_Root -> String;

    # Get name of basename:
    #
    os_string_basename:  Dir_Path -> String;

    # Get a human-readable (well, sort of) description:
    #
    describe:  File -> String;

    # Get a time stamp:
    #
    timestamp:  File -> timestamp::Timestamp;           # timestamp     is from   src/app/makelib/paths/timestamp.pkg

    # Portable encodings that avoid whitespace:
    #
    encode:  File -> String;
    decode:  Anchor_Dictionary -> String -> File;

    encoding_is_absolute:        String -> Bool;
        #
        # Check whether encoding (result
        # of "encode") is absolute --
        # i.e., not anchored and not relative:



    pickle:     { warn: (Bool, String) -> Void }
                ->
                { file:        Dir_Path,
                  relative_to: File
                }
                ->
                List( List(String) );



    unpickle:   Anchor_Dictionary
                ->
                { pickled:      List(  List(String) ),
                  relative_to:  File
                }
                ->
                Dir_Path;

};

# Overview:
#
#     Per unix tradition, .lib files may refer to files using
#     "absolute" file paths such as   /aa/bb/cc/... or
#     "relative" file paths such as    aa/bb/cc/...
#     where "aa" "bb" "cc" are called path "arcs".
#
#     In addition, makelib supports 
#     "anchored" file paths such as   $ROOT/aa/bb/cc/...
#     where "$ROOT" is an "anchor variable".
#          This allows us to move an entire directory of
#     sourcefiles from one spot to another in the filesystem
#     simply by updating one anchor variable setting.
#
#     Furthermore, makelib file syntax allows anchor variables
#     to have both a fixed default value, and also to be
#     temporarily rebound to another value within a given
#     syntactic scope:  We refer to these as the "free"
#     and "bound" values of the anchor variable respectively,
#     by analogy with lambda calculus nomenclature.
#
#     We give the arcs "." and ".." the special meanings
#     of respectively "current" and "parent" directory.
#
#     We also forbid whitespace in paths, to allow simple 
#     parsing of .lib files.
#
#     Some hosts may allow use of "." ".." as normal
#     arc names, and some host arc names may in fact include
#     whitespace.  We handle these cases by encoding the
#     arc names using octal escape sequences like \x2d 
#     for each problematic character.
#
#     Since the user may move around source files from
#     time to time and update anchor variables accordingly,
#     we attempt to evaluate anchor variables, and expressions
#     involving them, as late as possible in the compilation
#     process, by using thunks and lazy-style datastructure
#     techniques as appropriate.
#        This datastructure "laziness" is potentially
#     problematic in the case of paths specified relative to
#     the current working directory ("CWD"), since the CWD
#     may change from time to time, and our "laziness" could
#     thus result in a path being evaluated relative to an
#     unexpected -- and wrong -- CWD value.
#        To avoid this problem, we track the CWD and
#     implement a system of notifications for when the
#     CWD changes, so as to give the effect of evaluating 
#     path expressions as late as possible, but still
#     relative to the expected CWD value.
#
#     Another twist:  The above unix-like path specification
#     is portably supported on all platforms -- we call it
#     "standard" notation -- but sometimes we need access to
#     idiosyncratic functionalities of a particular host's
#     path syntax, in particular to the ability to specify
#     disk volumes on MS-DOS/MS-Windows, so we also support
#     use of the "native" path notation of the host os.
# -->    In .lib file surface syntax we use a leading "#" on <--
# --> native path expressions to distinguish them from         <--
# --> standard path expressions.                               <--
#
#     Yet another:  We provide facilities to "pickle" and
#     "unpickle" our file reference datastructures, which
#     is to say, to serialize them as bytestrings suitable
#     for storage in diskfiles and then deserialize such
#     bytestrings back into live datastructures.  This
#     lets us propagate state between executions of makelib.
#
#     We implement all this as follows:
#
#     o Our "anchors" are simply strings, which
#        we look up in string-keyed maps. 
#
#     o Paths aa/bb/cc/... are represented as lists of strings 
#          ["aa", "bb", "cc", ...]
#       except that mostly we're interested in being able
#       to add and remove arcs from the logical -end- of
#       the path, so we usually use -reversed- path lists
#          [ ..., "cc", "bb", "aa" ]
#
#     o Anchor values are recorded in an "anchor_dictionary"
#       which includes both a
#         a "free"    map recording the current free (default) values of anchors, and a
#         a "bound"   map recording current bound values of anchors.
#
#     o We define type Path_Root to represent the root of a path.
#   
#
#
# 2010-09-08 CrT:  Matthias Blume uses this facility heavily in SML/NJ,
#                  which I find makes the code harder to read -- this
#                  is the opposite of declarative programming style,
#                  one has mentally execute the code to guess what
#                  directory a given anchor points to at a given point
#                  in the computation.
#
#                  Consequently, in the Mythryl codebase I have reduced
#                  the set of anchors used to the single ROOT anchor,
#                  which points to the root of the Mythryl source code
#                  tree and never changes during a compile.
#
#                  I'm inclined to think this entire facility can and
#                  should be considerably simplified to accord more
#                  with standard posix programming practive.  It appears
#                  to do nothing that couldn't be done better with
#                  standard unix environment strings.


## Author: Matthias Blume
## Copyright (c) 2000 by Lucent Technologies, Bell Laboratories
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2015,
## released per terms of SMLNJ-COPYRIGHT.


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext